How to Solve Deodorant Evaporator in C


The challenge

This program tests the life of an evaporator containing a gas.

We know the content of the evaporator (content in ml), the percentage of foam or gas lost every day (evap_per_day) and the threshold (threshold) in percentage beyond which the evaporator is no longer useful. All numbers are strictly positive.

The program reports the nth day (as an integer) on which the evaporator will be out of use.

Example:

evaporator(10, 10, 5) -> 29

Note:

Content is in fact not necessary in the body of the function “evaporator”, you can use it or not use it, as you wish. Some people might prefer to reason with content, some other with percentages only. It’s up to you but you must keep it as a parameter because the tests have it as an argument.

The solution in C

Option 1:

#include <math.h>

int evaporator(double content, double evap_per_day, double threshold) {
  return (int) ceil(log(threshold/100) / log(1 - evap_per_day/100));
}

Option 2:

int evaporator(double content, double evap, double threshold) {
    unsigned short n = 0;
    for(float lost = content * (threshold/100); content > lost; n++)
      content -= content * (evap/100);
    return n;
}

Option 3:

int evaporator(double content, double evap_per_day, double threshold) {    
    int days;
    double percentage = 100;
    
    for(days = 0; percentage>=threshold; days++) {
      percentage *= (1-(evap_per_day/100));
    }     
    return days;
}

Test cases to validate our solution

#include <criterion/criterion.h>

extern int evaporator(double content, double evap_per_day, double threshold);

static void do_test(double content, double evap_per_day, double threshold, int expected)
{
	int actual = evaporator(content, evap_per_day, threshold);

	cr_assert_eq(actual, expected,
		"content = %f\n"
		"evap_per_day = %f\n"
		"threshold = %f\n"
		"expected %d, but got %d",
		content, evap_per_day, threshold,
		expected, actual
	);
}

Test(tests_suite, sample_tests)
{
    do_test(10, 10, 10, 22);
    do_test(10, 10, 5, 29);
    do_test(100, 5, 5, 59);
    do_test(50, 12, 1, 37);
    do_test(47.5, 8, 8, 31);
    do_test(100, 1, 1, 459);
    do_test(10, 1, 1, 459);
    do_test(100, 1, 5, 299);
}