/******************************************************************************
 * Perform analytics on a single dimension array
 * Count, sum, average, median, minimum, maximum, range, standard deviation
 * You can pass data points as args 
 ******************************************************************************/
import java.util.*;                 //import utility class

public class arrayAnalytics
{
    public static void main (String[] args) 
    {   
        double[] dataPoints = {-1, 4, 20.2, 6.5, 8, -60.53, 45, 0, 3};  //use if no data is provided;

        if (args.length > 0)                                            //if data points are provided
        {
            dataPoints = new double[args.length];                       //create an array
            for (int i=0; i < args.length; i++)                         //loop through all args
                dataPoints[i] = Double.parseDouble(args[i]);            //convert from string to double 
        }

        System.out.println("Data points.: " + Arrays.toString(dataPoints) );

        compute(dataPoints);    
    }

/**********************************************************************************
 * Perform array analytics computation
 * including: count, sum, average, minimum, maximum, median, standard deviation
 **********************************************************************************/
    static void compute(double[] dataPoints)
    {        
        Arrays.sort(dataPoints);
        System.out.println("Sorted Array: " + Arrays.toString(dataPoints) );
        System.out.println("Count.......: " + count(dataPoints)  ); 
        System.out.println("Sum.........: " + sum(dataPoints)    ); 
        System.out.println("Average.....: " + avg(dataPoints)    ); 
        System.out.println("Median......: " + median(dataPoints) ); 
        System.out.println("Minimum.....: " + min(dataPoints)    ); 
        System.out.println("Maximum.....: " + max(dataPoints)    ); 
        System.out.println("Range.......: " + range(dataPoints)  ); 
        System.out.println("Std.Dev.....: " + stdDev(dataPoints) ); 
    }
/**********************************************************************************
 * Count array elements
 **********************************************************************************/
    static int count(double[ ] array)
    {
        return array.length;
    }
/**********************************************************************************
 * Sum array elements
 **********************************************************************************/
    static double sum(double[ ] array)
    {
        double sum = 0;
        for (double element : array)
            sum += element;
        return sum;            
    }
/**********************************************************************************
 * Average array elements
 **********************************************************************************/
    static double avg(double[ ] array)
    {
        return (sum(array) / count(array));
    }
/**********************************************************************************
 * Minimum of array elements
 **********************************************************************************/
    static double min(double[ ] array)
    {
        double min = Double.POSITIVE_INFINITY;     //set to highest possible value
        for (double element : array)
            if (element < min)
                min = element;
        return min;            
    }
/**********************************************************************************
 * Maximum of array elements
 **********************************************************************************/
    static double max(double[ ] array)
    {
        double max = Double.NEGATIVE_INFINITY;     //set to lowest possible value
        for (double element : array)
            if (element > max)
                max = element;
        return max;            
    }
/**********************************************************************************
 * Range of array elements
 **********************************************************************************/
    static double range(double[ ] array)
    {
        return (max(array) - min(array));
    }
/**********************************************************************************
 * Median of array 
 **********************************************************************************/
    static double median(double[ ] array)
    {
        int count = count(array);
        Arrays.sort(array);                                 //sort the array
        double median = (count%2 == 1)                      //if count is odd
            ?  array[count/2]                               //median= mid point 
            : (array[count/2] + array[count/2-1]) / 2;      //median= average of 2 mid points
        return median;
    }
/**********************************************************************************
 * Standard Deviation of array 
 **********************************************************************************/
    static double stdDev(double[ ] array)
    {
        double stdDev   = 0;
        double sqrDelta = 0;                            //square of deltas      
        int    count = count(array);
        double avg   = avg(array);
        for (double element : array)                    //loop through all elements                 
            sqrDelta += Math.pow(element-avg,2);        //add to square of delta
        stdDev = Math.sqrt(sqrDelta/count);             //square root of average(square of deltas)
        return stdDev;
    }
}