javafordummies javafordummies - 7 months ago 42
Java Question

How to remove value, determine minimum of remaining values

I need to determine the minimum value after removing the first value.

For instance is these are the numbers 0.5 70 80 90 10

I need to remove 0.5, the determine the minimum value in the remaining numbers. calweightAvg is my focus ...

The final output should be “The weighted average of the numbers is 40, when using the data 0.5 70 80 90 10, where 0.5 is the weight, and the average is computed after dropping the lowest of the rest of the values.”

EDIT: Everything seems to be working, EXCEPT during the final out put. "The weighted average of the numbers is 40.0, when using the data 70.0, 80.0, 90.0, 10.0, where 70.0 (should be 0.5) is the weight, and the average is computed after dropping the lowest of the rest of the values."

So the math is right, the output is not.

/*
*
*/
package calcweightedavg;
import java.util.Scanner;
import java.util.ArrayList;

import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.io.IOException;


public class CalcWeightedAvg {

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {

//System.out.println(System.getProperty("user.dir"));
ArrayList<Double> inputValues = getData(); // User entered integers.
double weightedAvg = calcWeightedAvg(inputValues); // User entered weight.
printResults(inputValues, weightedAvg); //Weighted average of integers.

}

public class CalcWeightedAvg {

/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {

//System.out.println(System.getProperty("user.dir"));
ArrayList<Double> inputValues = getData(); // User entered integers.
double weightedAvg = calcWeightedAvg(inputValues); // User entered weight.
printResults(inputValues, weightedAvg); //Weighted average of integers.

}

public static ArrayList<Double> getData() throws FileNotFoundException {

// Get input file name.
Scanner console = new Scanner(System.in);
System.out.print("Input File: ");
String inputFileName = console.next();
File inputFile = new File(inputFileName);

//
Scanner in = new Scanner(inputFile);
String inputString = in.nextLine();

//
String[] strArray = inputString.split("\\s+"); //LEFT OFF HERE

// Create arraylist with integers.
ArrayList<Double> doubleArrayList = new ArrayList<>();
for (String strElement : strArray) {
doubleArrayList.add(Double.parseDouble(strElement));
}

in.close();

return doubleArrayList;
}


public static double calcWeightedAvg(ArrayList<Double> inputValues){
//Get and remove weight.
Double weight = inputValues.get(0);
inputValues.remove(0);

//Sum and find min.
double min = Double.MAX_VALUE;
double sum = 0;
for (Double d : inputValues) {
if (d < min) min = d;
sum += d;
}

// Calculate weighted average.
return (sum-min)/(inputValues.size()-1) * weight;


}

public static void printResults(ArrayList<Double> inputValues, double weightedAvg) throws IOException {
Scanner console = new Scanner(System.in);
System.out.print("Output File: ");
String outputFileName = console.next();
PrintWriter out = new PrintWriter(outputFileName);

System.out.println("Your output is in the file " + outputFileName);

out.print("The weighted average of the numbers is " + weightedAvg + ", ");
out.print("when using the data ");
for (int i=0; i<inputValues.size(); i++) {
out.print(inputValues.get(i) + ", ");
}
out.print("\n where " + inputValues.get(0) + " is the weight, ");
out.print("and the average is computed after dropping the lowest of the rest of the values.\n");

out.close();
}


}

Answer

to do this task in a complexity of O(n) isn't a hard task. you can use ArrayList's .get(0) to Save weight in a temp variable, then use .remove(0) function which removes the first value (in this case 0.5)

then you should use a For Each loop for (Double d : list) to sum AND find the minimal value

afterwards subtract the minimum value from the sum. and apply weight to the sum (in this case you'll end up with 240*0.5 = 120; 120\3 = 40;

finally, you can use ArrayList's .size()-1 function to determine the divisor.

The problem in your code:

  • in your implementation you've removed the weight item from list. then multiplied by the first item in the list even though it's no longer the weight:

return (sum-min)/(inputValues.size()-1) * inputValues.get(0);

  • your calculation than was: ((70+80+90+10)-10)/(4-1) * (70) = 5600
if(inputValues.size() <= 1){
       inputValues.remove(0);
    }
  • this size safeguard will not remove weight from the list. perhaps you've meant to use >=1
  • even if that was your intention this will not result in a correct computation of your algorithm in the edge cases where size==0\1\2 I would recommend that you re-think this.

the full steps that need to be taken in abstract code:

ArrayList<Double> list = new ArrayList();
        // get and remove weight
        Double weight = list.get(0);
        list.remove(0);
        // sum and find min
        double min=Double.MAX_VALUE;
        double sum=0;
        for (Double d : list) {
            if (d<min) min = d;
            sum+=d;
        }
        // subtract min value from sum
        sum-=min;
        // apply weight
        sum*=weight;
        // calc weighted avg
        double avg = sum/list.size()-1;
        // viola!

do take notice that you can now safely add weight back into the array list after its use via ArrayList's .add(int index, T value) function. also, the code is very abstract and safeguards regarding size should be implemented.

Regarding your Edit:

it appears you're outputting the wrong variable.

out.print("\n where " + inputValues.get(0) + " is the weight, ");

the weight variable was already removed from the list at this stage, so the first item in the list is indeed 70. either add back the weight variable into the list after you've computed the result or save it in a class variable and input it directly.

change for class:

public class CalcWeightedAvg { 

static double weight=0;
//...
}

change for function:

public static double calcWeightedAvg(ArrayList<Double> inputValues){
   //Get and remove weight.
   weight = inputValues.get(0); // changed to class variable
//...
}