transiti0nary
transiti0nary

Reputation: 513

Implementing algorithm with only integer arithmetic, multiple fuel consumption rates for a Car

I need to implement an algorithm to drive a Car object. This specific type of car consumes fuel at a higher rate for a while at the beginning of the journey, and at a lower rate from thereon. I'm struggling to implement the algorithm using only integer arithmetic (as requested), whilst ensuring it works accurately.

Currently it is like so:

    int driven = 0;
    int fuelConsumed = 0;

    while (driven <= kilometresToDrive && driven <= 50) {
        // consume at 1l per 15km while journey is less than 50km
        driven += 15;
        fuelConsumed++;
    } 

    while (driven <= kilometresToDrive && driven > 50) {
        // consume at 1l per 20km while journey is greater than 50km
        driven += 20;
        fuelConsumed++;
    }

Now evidently the issue is that the first loop will hit 60 before jumping into the second loop, and the rate is supposed to change after hitting 50k. Now I can check again before incrementing fuelConsumed that it hasn't yet gone beyond 50k, but then it'll jump into the second loop and increment driven by another 20k without even using any fuel, which is another big problem. I've considered a bunch of different options but they all seem to have some drawback. Is there any way to do this using only integer arithmetic or is my implementation above as good as it gets?

EDIT:

I should add, they way we were told it was supposed to work is that for any journey up to 15km, it uses one litre, up to 30km = 2 litres, up to 45km = 3 litres etc. Then after 50, same deal but litresConsumed jumps by one every time it drives another 20k instead of 15

Upvotes: 1

Views: 102

Answers (3)

Andreas
Andreas

Reputation: 159086

If you are limited to integer math, then result cannot be fully accurate. What if kilometresToDrive is 40? Is that 2 or 3 liters? Technically it's 40 / 15 = 2.666667 liters. Are you supposed to round that up, because integer math does truncation, not rounding, so in pure integer math, it would be 2.

Anyway, don't use loops. Calculate the result.

If less than 50, it's just kilometresToDrive / 15.

If more than 50, the formula would be 50 / 15 + (kilometresToDrive - 50) / 20. To reduce rounding errors, you should defer rounding to the end, so multiply and divide by 60:

50 / 15 + (kilometresToDrive - 50) / 20
(50 / 15 * 60 + (kilometresToDrive - 50) / 20 * 60) / 60
(50 * 4 + kilometresToDrive * 3 - 50 * 3) / 60
(50 + kilometresToDrive * 3) / 60

This means your code will be:

int fuelConsumed = (kilometresToDrive <= 50
                    ? kilometresToDrive / 15
                    : (50 + kilometresToDrive * 3) / 60);

Update

It is supposed to work so that for any journey up to 15km, it uses one litre, up to 30km = 2 litres, up to 45km = 3 litres etc.

This requirement means that the math needs to round up, not truncate the way integer math does. To force a round-up in integer math, you add one less than the divisor before dividing.

Example: 1 / 15 = 0 is normal integer math.
(1 + 14) / 15 = 1 is integer math for doing round-up logic.

So, to get rounded-up result, we adjust the formulas:
x / 15(x + 14) / 15
(50 + x) / 60(50 + x + 59) / 60(109 + x) / 60

int fuelConsumed = (kilometresToDrive <= 50
                    ? (14 + kilometresToDrive) / 15
                    : (109 + kilometresToDrive * 3) / 60);

If you want to verify the result, you could do floating-point math:

double fuelConsumed = (kilometresToDrive <= 50
                       ? kilometresToDrive / 15d
                       : 50 / 15d + (kilometresToDrive - 50) / 20d);
fuelConsumed = Math.ceil(fuelConsumed);  // Round Up

Upvotes: 3

Eritrean
Eritrean

Reputation: 16498

try to increase driven by +1 and only add fuelConsumed when you reach multiple of 15 if driven is less than 50 and multiple of 20 but after substracting 50 from driven so that the first increase is by 70 km.

public static void main(String [] args){
    int driven = 0;
    int fuelConsumed = 0;

    System.out.println("before 50");
    while (driven <= 200 && driven <= 50) {
        // consume at 1l per 15km while journey is less than 50km
        driven += 1;
        if (driven%15==0){
            fuelConsumed++;
            System.out.println("driven:  "+driven);
            System.out.println("fuelConsumed:  "+fuelConsumed);
        }        
    } 
    System.out.println("after 50");
    while (driven <= 200 && driven > 50) {
        // consume at 1l per 20km while journey is greater than 50km
        driven += 1;
        if ((driven-50)%20==0){
            fuelConsumed++;
            System.out.println("driven:  "+ driven);
            System.out.println("fuelConsumed:  "+fuelConsumed);
        }
    }
}

Upvotes: 0

user3965604
user3965604

Reputation:

If you're strictly using integers, you'll just have to implement a counter so you don't have to go in such big steps. You can use the following.

int driven = 0;
int fuelConsumed = 0;
int cnt = 0;

while (driven <= kilometresToDrive && driven <= 50) {
    // consume at 1l per 15km while journey is less than 50km
    driven++;
    cnt++;
    if(cnt==15){fuelConsumed++;cnt=0;}
} 

while (driven <= kilometresToDrive && driven > 50) {
    // consume at 1l per 20km while journey is greater than 50km
    driven++;
    cnt++;
    if(cnt==20){fuelConsumed++;cnt=0;}
}

Upvotes: 0

Related Questions