## DEV Community is a community of 906,671 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

dev.to staff

Posted on

# Daily Challenge #61 - Evolution Rate

Write a function getEvolutionRateMessage which takes two numbers before & after. The before value is the initial value of the evolution. The after value is the value after its evolution. An evolution can be calculated as follows:

`evolution = (after - before) / before * 100`

This function will return a string such that there are three possible outputs:
"A positive evolution of X%."
"A negative evolution of Y%."
"No evolution."

Examples:

getEvolutionRateMessage 11.29 45.79
getEvolutionRateMessage 95.12 66.84
getEvolutionRateMessage 0 27.35
getEvolutionRateMessage 41.26 0
getEvolutionRateMessage 1.26 1.26

"A positive evolution of 306%."
"A negative evolution of 30%."
"A positive evolution of 2735%."
"A negative evolution of 4126%."
"No evolution."

This challenge comes from aminnairi here on DEV. Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

## Discussion (26)

SavagePixie • Edited on

Some JavaScript.

``````const getEvolutionRateMessage = (before, after) => {
const evolution = before == 0 ? after * 100
: after == 0 ? -before * 100
: Math.round((after - before) / before * 100)

return evolution == 0 ? "No evolution."
: evolution > 0 ? `A positive evolution of \${evolution}℅.`
: `A negative evolution of \${Math.abs(evolution)}%.`
}
``````
Amin

Hi there, nice and short solution! I believe the case for the values `0` & `27.35` wont give what you expected. But you are in the right path for sure.

SavagePixie

Fixed!

Melvin Yeo

I wrote it in Python, kept it as short as possible while maintaining clarity. 😎

``````def getEvolutionRateMessage(before, after):
if before == after:
return "No evolution"

polarity = "positive" if after > before else "negative"
evo_rate = round(abs(after - before) * 100 / (before if before != 0 and after != 0 else 1))

return f"A {polarity} evolution of {evo_rate}%"
``````
Amin

Neat! I like what they did with this new string interpolation thing in Python.

I Didn't know it was called a polarity. Learning new things every day. Yay!

Khalyomede

Since no one proposed a PHP solution, here I am!

``````if (!function_exists("getEvolutionRate")) {
function getEvolutionRate(float \$before, float \$after): float {
if (\$before === 0.0) {
return \$after * 100;
}

if (\$after === 0.0) {
return -(\$before * 100);
}

return round((\$after - \$before) / \$before * 100);
}
}

if (!function_exists("getEvolutionRateMessage")) {
function getEvolutionRateMessage(float \$before, float \$after): string {
\$evolutionRate = getEvolutionRate(\$before, \$after);
\$evolutionRateToDisplay = abs(\$evolutionRate);
\$direction = \$evolutionRate > 0 ? "positive" : "negative";

return \$evolutionRate === 0.0 ? "No evolution" : "A \$direction evolution of \$evolutionRateToDisplay%";
}
}
``````

`getEvolutionRate()` unit tests:

``````use PHPUnit\Framework\TestCase;

class GetEvolutionRateTest extends TestCase
{
public function testShouldReturnPositiveRate()
{
\$this->assertEquals(getEvolutionRate(11.29, 45.79), 306);
}

public function testShouldReturnOtherPositiveRate()
{
\$this->assertEquals(getEvolutionRate(0, 27.35), 2735);
}

public function testShouldReturnNegativeRate()
{
\$this->assertEquals(getEvolutionRate(95.12, 66.84), -30);
}

public function testShouldReturnOtherNegativeRate()
{
\$this->assertEquals(getEvolutionRate(41.26, 0), -4126);
}

public function testShouldReturnZeroEvolution()
{
\$this->assertEquals(getEvolutionRate(1.26, 1.26), 0);
}
}
``````

`getEvolutionRateMessage()` unit tests:

``````use PHPUnit\Framework\TestCase;

class GetEvolutionRateMessageTest extends TestCase
{
public function testShouldReturnPositiveRateMessage()
{
\$this->assertEquals(getEvolutionRateMessage(11.29, 45.79), "A positive evolution of 306%");
}

public function testShouldReturnOtherPositiveRateMessage()
{
\$this->assertEquals(getEvolutionRateMessage(0, 27.35), "A positive evolution of 2735%");
}

public function testShouldReturnNegativeRateMessage()
{
\$this->assertEquals(getEvolutionRateMessage(95.12, 66.84), "A negative evolution of 30%");
}

public function testShouldReturnOtherNegativeRateMessage()
{
\$this->assertEquals(getEvolutionRateMessage(41.26, 0), "A negative evolution of 4126%");
}

public function testShouldReturnZeroEvolutionMessage()
{
\$this->assertEquals(getEvolutionRateMessage(1.26, 1.26), "No evolution");
}
}
``````
Amin

I love those guards you are puting in your code. Really makes me want to go back and do PHP with you like the good ol'times!

Khalyomede • Edited on

Let's do a side project together

Donald Feury

All this talk of evolution makes me want to Go play Pokemon again. Holy crap I haven't played that in a long time!

rate.go

``````package evolution

import "fmt"

const (
negative string = "A negative evolution of %.f%%."
positive string = "A positive evolution of %.f%%."
neutral  string = "No evolution."
)

// Rate indicates the evolution percentage based on the before and after values
func Rate(before float64, after float64) string {
if before == 0 {
return fmt.Sprintf(positive, after*100)
}

if after == 0 {
return fmt.Sprintf(negative, before*100)
}

rate := (after - before) / before * 100

if rate > 0 {
return fmt.Sprintf(positive, rate)
}

if rate < 0 {
return fmt.Sprintf(negative, rate*-1)
}

return neutral
}

``````

rate_test.go

``````package evolution

import "testing"

type testCase struct {
description string
input       []float64
expected    string
}

func TestRate(t *testing.T) {
testCases := []testCase{
{
"a positive evolution rate",
[]float64{11.29, 45.79},
"A positive evolution of 306%.",
},
{
"a negative evolution rate",
[]float64{95.12, 66.84},
"A negative evolution of 30%.",
},
{
"zero before value",
[]float64{0, 27.35},
"A positive evolution of 2735%.",
},
{
"zero after value",
[]float64{41.26, 0},
"A negative evolution of 4126%.",
},
{
"same before and after values",
[]float64{1.26, 1.26},
"No evolution.",
},
}

for _, test := range testCases {
if result := Rate(test.input[0], test.input[1]); result != test.expected {
t.Fatalf("FAIL: %s - Rate(%+v): %s - expected: %s", test.description, test.input, result, test.expected)
}
t.Logf("PASS: %s", test.description)
}
}

``````
Amin

I always love your take at these challenges in Go. I should get started soon. Looking sharp as always!

And yes, Pokemon is just timelessly good. I could play it all my life haha!

Donald Feury

Ah shucks, I am humbled by the praise.

You should, Go is a very easy language to pick up and use.

Only part that may require a little more effort to understand is the concurrency related features of it but just pick those up as you need them.

Craig McIlwrath

``````getEvolutionRateMessage :: Double -> Double -> String
getEvolutionRateMessage before after
| evol > 0  = "A positive evolution of " ++ show evol ++ "%."
| evol == 0 = "No evolution."
| evol < 0  = "A negative evolution of " ++ show (0-evol) ++ "%."
where evol = (after - before) / before * 100
``````
Amin

I long awaited this one. Haha!

Cagatay Kaya

Here is a Javascript arrow function, that uses nested ternary operators. Someone probably already posted this answer, but hey main point is that I took the challenge and solved by myself.

``````const getEvolutionRateMessage = (before, after) => {
const rate = Math.round(
(((after == 0 ? -before * before + before : after) - before) /
(before == 0 ? 1 : before)) *
100
);
return rate == 0
? "No evolution."
: rate > 0
? `A positive evolution of \${rate}%.`
: `A negative evolution of \${-1 * rate}%.`;
};
``````
Amin

Thanks for showing us your solution. What's important is what you achieve at the end of the day!

E. Choroba • Edited on

Perl solution. I still don't understand how the values are computed for zeroes, but it passes the tests :-)

``````#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

sub get_evolution_rate_message {
my (\$before, \$after) = @_;
return 'No evolution.' if \$before == \$after;
return sprintf 'A %s evolution of %.0f%%.',
qw(_ negative positive)[ \$before <=> \$after ],
abs((\$before - (\$after || (\$before+\$before ** 2)))
* 100 / (\$before || 1))
}

use Test::More tests => 5;

is get_evolution_rate_message(11.29, 45.79), 'A positive evolution of 306%.';
is get_evolution_rate_message(95.12, 66.84), 'A negative evolution of 30%.';
is get_evolution_rate_message(0, 27.35),     'A positive evolution of 2735%.';
is get_evolution_rate_message(41.26, 0),     'A negative evolution of 4126%.';
is get_evolution_rate_message(1.26, 1.26),   'No evolution.';
``````
Amin

Imagine that instead of going from 0 to 27.35, you are going from 0.0000000001 to 27.35. I think you'll have your answer here. 😉

cvanpoelje • Edited on

My javascript solution :

``````const getEvolutionRateMessage = (before, after) => {
evolution =
before > 0 ? ((after - before) / before) * 100 : (after - before) * 100;
return evolution === 0
? "No Evolution"
: `A \${evolution > 0 ? "Positive" : "Negative"} evolution of \${Math.abs(
evolution
).toFixed(2)}%`;
}
``````
Avalander • Edited on

My knowledge of statistics is a bit rusty (yet I didn't use rust for this challenge), but I think that an increase from 0 to anything is basically an infinite rate and a decrease from anything to 0 is a negative 100% rate, so I disagree with the examples 3 and 4 and have written my solution accordingly.

``````get_rate :: Double -> Double -> String
get_rate before after
| before == after = "No evolution."
| before == 0     = "Infinite evolution."
| evolution < 0   = "A negative evolution of " ++ (show' . abs) evolution ++ "%."
| otherwise       = "A positive evolution of " ++ show' evolution ++ "%."
where
evolution = (after - before) * 100 / before
show'     = show . round
-- show_abs = show' . abs -- Hmm, maybe not the best name ever, let's leave it out.
``````

### Output

``````get_rate 11.29 45.79 -- "A positive evolution of 306%."
get_rate 95.12 66.84 -- "A negative evolution of 30%."
get_rate 0 27.35     -- "Infinite evolution."
get_rate 41.26 0     -- "A negative evolution of 100%."
get_rate 1.26 1.26   -- "No evolution."
``````
Dev Prakash
``````def getEvolutionratemessage (before , after) :
try :
evolution = (after - before ) / before * 100
except ZeroDivisionError :
return "can't divide by zero "

if evolution > 0 :
statement = f"A Positive evolution of {round(evolution)}%"
elif evolution < 0:
statement = f"A Negative evolution of {round(evolution)}%"
else :
statement = f"No evolution"
return statement

print (getEvolutionratemessage(95.12 , 66.84))

``````
Mat-R-Such

python

``````def getEvolutionRateMessage(before,after):
if before == 0 and after == 0:  return "No evolution."
evolution = after * 100 if before == 0 else  before * 100 if after == 0 else round(((after-before) / before)*100)
return "A positive evolution of "+str(int(evolution))+'%' if before<after else "A negative evolution of "+str(int(evolution*-1) if evolution <0 else int(evolution))+'%' if before > after else "No evolution."
``````
Dev Prakash
Melvin Yeo

The code will throw an error if you pass in the following parameters
`getEvolutionRateMessage 0 27.35` as you're dividing by 0.

Dev Prakash

Oyeeeeee
Thanks a lot , man
I appreciate it ...
Can u help me with how to publish my codes here in comment section ...
I don't really understand this markdown and all ...