Solving Speed Control in Java


The challenge

In John’s car the GPS records every s seconds the distance travelled from an origin (distances are measured in an arbitrary but consistent unit). For example, below is part of a record with s = 15:

x = [0.0, 0.19, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25]

The sections are:

0.0-0.19, 0.19-0.5, 0.5-0.75, 0.75-1.0, 1.0-1.25, 1.25-1.50, 1.5-1.75, 1.75-2.0, 2.0-2.25

We can calculate John’s average hourly speed on every section and we get:

[45.6, 74.4, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0]

Given s and x the task is to return as an integer the *floor* of the maximum average speed per hour obtained on the sections of x. If x length is less than or equal to 1 return `` since the car didn’t move.

Example:

with the above data your function gps(s, x)should return 74

Note

With floats it can happen that results depends on the operations order. To calculate hourly speed you can use:

(3600 * delta_distance) / s.

The solution in Java code

Option 1:

import java.util.*;
import java.util.stream.*;

public class GpsSpeed {
    
    public static int gps(int s, double[] x) {
        double maxSpeed = IntStream
          .range(0, x.length - 1)
          .mapToDouble(i -> (x[i+1] - x[i]) * 3600.0 / (double) s )
          .max().orElse(0.0);
        return (int) Math.floor(maxSpeed);
    }
}

Option 2:

public class GpsSpeed {
    
    public static int gps(int s, double[] x) {
       double maxDiff = 0.0;
        for(int i = 0; i < x.length -1; i++){
          maxDiff = Math.max(x[i+1] - x[i], maxDiff);
        }
        return (int)Math.floor(maxDiff*3600.0/s);
    }
}

Option 3:

public class GpsSpeed {
    
    public static int gps(int s, double[] x) {
        int maxSpeed = 0;
        for ( int i=0; i<x.length-1; i++ ) {
            int avrSpeed = (int) ( 3600 * ( x[i+1] - x[i] ) / s );
            maxSpeed = ( maxSpeed < avrSpeed ) ? avrSpeed : maxSpeed;
        }
        
        return maxSpeed;
    }
}

Test cases to validate our solution

import static org.junit.Assert.*;
import org.junit.Test;

public class GpsSpeedTest {
    
    private static void testing(long actual, long expected) {
        assertEquals(expected, actual);
    }
    
    @Test
    public void test1() {
        System.out.println("Fixed Tests: gps"); 
        double[] x = new double[] {0.0, 0.23, 0.46, 0.69, 0.92, 1.15, 1.38, 1.61};
        testing(GpsSpeed.gps(20, x), 41);
        x = new double[] {0.0, 0.11, 0.22, 0.33, 0.44, 0.65, 1.08, 1.26, 1.68, 1.89, 2.1, 2.31, 2.52, 3.25};
        testing(GpsSpeed.gps(12, x), 219);
        x = new double[] {0.0, 0.18, 0.36, 0.54, 0.72, 1.05, 1.26, 1.47, 1.92, 2.16, 2.4, 2.64, 2.88, 3.12, 3.36, 3.6, 3.84};
        testing(GpsSpeed.gps(20, x), 80);
    }
}