WessCoby
12/19/2018 - 11:09 PM

Codewares Kata

Codewares Kata

/*
* You are the "computer expert" of a local Athletic Association (C.A.A.). Many teams of runners come to compete.
* Each time, you get a string of all race results of every team who has run.
* For example, here is  string showing the individual results of a team of 5 runners: "01|15|59, 1|47|6, 01|17|20, 1|32|34, 2|3|17"
* Each part of the string is of the form: h|m|s where h,m,s (h for hour, m for minutes, s for seconds) are positive or null integers,
* (represented as strings) with one or two digits. There are no traps in this format.
* To compare the results of the teams you are asked for giving three statistics; range, average and median
*
* Range: difference between the lowest and highest values. In {4, 6, 9, 3, 7}, the lowest value is 3 and highest is 9 so the range is 9 - 3 = 6
*
* Mean or Average: To calculate the mean, add together all of the numbers in the set and then divide the sum by the total count of the numbers
*
* Median: In statistics, the median is the number separating the higher half of a data sample from the lower half.
* The median of a finite list of numbers can be found by arranging all the observations from the lowest value to the highest value and
* picking the middle one (e.g. the median of {3, 3, 5, 9, 11} is 5) when there is an odd number of observations.
* If there is an even number of observations, then there is no single middle value; the median is then defined to be the mean of the two
* middle values (the median of {3, 5, 6, 9} is (5 + 6) / 2 = 5.5).
*
* Your task is to return a string giving these 3 values. For the example given above, the string result will be:
* "Range: 00|47|18 Average: 01|35|15 Median: 01|32|34" of the form: "Range: hh|mm|ss Average: hh|mm|ss Median: hh|mm|ss"
* where hh, mm, ss are integers (represented by strings) with each 2 digits
*
* Remarks:
* 1. If a result in seconds is ab.xy..., it will be given truncated as ab.
* 2. If the given string is "" you will return "".
* */

const stat = givenString => {
    // Adding zeros in the right place to properly format time strings
    let add_leading_zero = number => {
        if (number <= 9) {
            number = '0' + number;
        }
        return number;
    };

    // convert time from hh:mm:ss to seconds and vice versa
    let two_way_time_convert = time => {
        if( /(\w{1,2}):(\w{1,2}):(\w{1,2})/.test(time)) {
            // convert from hh:mm:ss to seconds
            let timeArray = time.split(":");
            return (parseInt(timeArray[0]) * 3600) + (parseInt(timeArray[1]) * 60) + parseInt(timeArray[2]);
        } else {
            // convert from seconds to hh:mm:ss
            let hr = Math.floor(time / 3600),
                min = Math.floor((time - (hr * 3600)) / 60),
                sec = time - (hr * 3600) - (min * 60);
            return `${add_leading_zero(hr)}:${add_leading_zero(min)}:${add_leading_zero(sec)}`
        }
    };

    // Check length of string
    if(givenString.length === 0) {
        // return empty string
        return "";
    } else {
        // Convert givenString to an array of time values (in seconds)
        // using iife (Immediately invoked function expression)
        let timeArray = (string_param =>
            string_param.split(",")
                .map(item => item.replace(/\|/g, ":"))
                .map(two_way_time_convert))(givenString);

        // find range, mean and median and convert result from seconds to hh:mm:ss
        // using iife
        let range = ((arr) =>
            two_way_time_convert((Math.max.apply(Math, arr) - Math.min.apply(Math, arr))).replace(/:/g, "|"))(timeArray);

        let median = (arr => {
            // sort array in ascending order
            arr.sort((a, b) => a - b);
            // checking if length of array is even
            if (arr.length % 2 === 0) {
                // find the average of the 2 center numbers
                let half = Math.floor(arr.length / 2);
                let med1 = arr[half - 1],
                    med2 = arr[half];
                return two_way_time_convert(((med1 + med2) / 2)).replace(/:/g, "|");
            } else {
                // return the number at the center
                let half = Math.floor(arr.length / 2);
                return two_way_time_convert(arr[half]).replace(/:/g, "|");
            }
        })(timeArray);

        let mean = (arr => {
            let sum = arr.reduce((prev, next) => prev + next),
                quantity = arr.length;
            return two_way_time_convert(Math.floor((sum / quantity))).replace(/:/g, "|");
        })(timeArray);

        // return the result
        return `Range: ${range} Average: ${mean} Median: ${median}`;
    }
 };
console.log(stat("01|15|59, 1|47|6, 01|17|20, 1|32|34, 2|3|17")); 

/* Output
*  Range: 00|47|18 Average: 01|35|15 Median: 01|32|34
*/