Converting single dimesnional arrays into a multi-dimensional array - java

I'm trying to convert my single dimensional array into a multidimensional array [5][7]. I know I have to convert my methods sortBySimpleInterest and displayInterest to accept a single multidimensional array instead of multiple single dimensional arrays. With making those two methods into a multidimensional array will I have to change the calculation to accept multidimensional arrays as well? I am also confused on how I should set up the SortbySimpleInterest method using the selection sort. Thanks for the help, I'm new to java
import java.util.Scanner;
public class InterestCalculatorBatchMDA {
public static void main(String[] args )
{
int cnt = 0;
double[][] arrPrincipalAmt = new double[5][7];
double[][] arrInterestRate = new double[5][7];
double[][] arrTerm = new double[5][7];
double[][] arrSimple = new double[5][7];
double[][] arrCompoundMonthly = new double[5][7];
double[][] arrCompoundDaily = new double[5][7];
double[][] arrCompoundWeekly = new double[5][7];
do{
arrPrincipalAmt[cnt] = getPrincipalAmount(1);
arrInterestRate[cnt] = getInterestRate(1);
arrTerm[cnt] = getTerm(1);
arrSimple[cnt] = round(calculateSimpleInterest(arrPrincipalAmt[cnt], arrInterestRate[cnt], arrTerm[cnt]),5);
arrCompoundMonthly[cnt] = round(calculateCompoundInterest(arrPrincipalAmt[cnt], arrInterestRate[cnt],arrTerm[cnt] ,12.0 ),5);
arrCompoundWeekly[cnt] = round(calculateCompoundInterest(arrPrincipalAmt[cnt], arrInterestRate[cnt], arrTerm[cnt], 52.0 ),5);
arrCompoundDaily[cnt] = round(calculateCompoundInterest(arrPrincipalAmt[cnt], arrInterestRate[cnt], arrTerm[cnt], 365.0 ),5);
cnt++;
}while (cnt < 5 && askYesNo("Enter another set of data (Yes/No):"));
displayInterest(arrPrincipalAmt,arrInterestRate,arrTerm,arrSimple,arrCompoundMonthly,arrCompoundWeekly,arrCompoundDaily,cnt);
sortBySimple(arrPrincipalAmt,arrInterestRate,arrTerm,arrSimple,arrCompoundMonthly,arrCompoundWeekly,arrCompoundDaily,cnt);
displayInterest(arrPrincipalAmt,arrInterestRate,arrTerm,arrSimple,arrCompoundMonthly,arrCompoundWeekly,arrCompoundDaily,cnt);
}
/** Round **/
public static double round(double numb1, double numb2) {
double round = ((double) Math.round(numb1*(Math.pow(10, numb2)))/(Math.pow(10, numb2)));;
return round;
}
/** Calculate Simple **/
public static double calculateSimpleInterest(double numb1, double numb2, double numb3) {
double calculateSimpleInterest = ((numb1)*(numb2/100.0)*(numb3/12.0));
return calculateSimpleInterest;
}
/** Calculate Compounded Daily **/
public static double calculateCompoundInterest(double numb1, double numb2, double numb3, double numb4 ) {
double calculateCompoundInterest = (numb1*Math.pow((1.0+((numb2/100.0)/numb4)),(numb4*(numb3/12.0))))-numb1;
return calculateCompoundInterest;
}
/** Get principal amount **/
public static double getPrincipalAmount(double numb1) {
Scanner input = new Scanner(System.in);
double numb2 = 1;
do{System.out.print("Enter Loan Amount: ");
numb2 = input.nextDouble();
if(numb2 > 0);
else{
System.out.println("Data Error: Loan amount must be greater than zero. You entered " +numb2);
}
}while (numb2 < 0);
return numb2;
}
/** Get interest rate **/
public static double getInterestRate(double numb1) {
Scanner input = new Scanner(System.in);
double numb2=1;
do{System.out.print("Enter Yearly Interest Rate (1 to 100 percent): ");
numb2 = input.nextDouble();
double getInterestRate = 0;
if (numb2 >= 0 && numb2 <= 100)
getInterestRate = numb2;
else{
System.out.println("Data Error: Interest rate must be greater than or equal to zero and less than or equal to 100. You entered " +numb2);
}
}while (numb2 <= 0 || numb2 >= 100);
return numb2;
}
/** Get term **/
public static double getTerm(double numb1) {
Scanner input = new Scanner(System.in);
double numb2=1;
do{System.out.print("Enter the Term (in months): ");
numb2 = input.nextInt();
double getTerm = 0;
if (numb2 > 0)
getTerm = numb2;
else{
System.out.println("Data Error: Loan amount must be greater than zero. You entered " +numb2);
}
}while (numb2 <= 0);
return numb2;
}
/** Sort by simple interest **/
public static void sortBySimple(double[][] arrPrincipalAmt ,double[][] arrInterestRate, double[][] arrTerm, double[][] arrSimple, double[][] arrCompoundMonthly, double[][] arrCompoundWeekly, double[][] arrCompoundDaily, double count){
for(int i = 0;i<count;i++)
{
for(int j=i+1; j<count;j++)
{
if(arrSimple[j]<arrSimple[i])
{
double temp = arrSimple[i];
arrSimple[i] = arrSimple[j];
arrSimple[j] = temp;
double temp1 = arrPrincipalAmt[i];
arrPrincipalAmt[i] = arrPrincipalAmt[j];
arrPrincipalAmt[j] = temp1;
double temp2 = arrInterestRate[i];
arrInterestRate[i] = arrInterestRate[j];
arrInterestRate[j] = temp2;
double temp3 = arrTerm[i];
arrTerm[i] = arrTerm[j];
arrTerm[j] = temp3;
double temp4 = arrSimple[i];
arrSimple[i] = arrSimple[j];
arrSimple[j] = temp4;
double temp5 = arrCompoundMonthly[i];
arrCompoundMonthly[i] = arrCompoundMonthly[j];
arrCompoundMonthly[j] = temp5;
double temp6 = arrCompoundDaily[i];
arrCompoundDaily[i] = arrCompoundDaily[j];
arrCompoundDaily[j] = temp6;
double temp7 = arrCompoundDaily[i];
arrCompoundDaily[i] = arrCompoundDaily[j];
arrCompoundDaily[j] = temp7;
}
}
}
}
/** Display Interest **/
public static void displayInterest(double[][] amt ,double[][] interest, double[][] term, double[][] simple, double[][] monthly, double[][] weekly, double[][] arrCompoundDaily, int count){
int i=0;
System.out.println("[Line #] [Principal Amount] [Interest Rate] [Term] [Simple Interest] [Compound Monthly] [Compound Weekly] [Compound Daily]");
do{
System.out.print((i+1)+" ");
System.out.print(amt[i]+" ");
System.out.print(+interest[i]+" ");
System.out.print(+ term[i]+" ");
System.out.print(+simple[i]+" ");
System.out.print(+monthly[i]+" ");
System.out.print(+weekly[i]+" ");
System.out.println(+arrCompoundDaily[i]);
i++;
}while(i < count);
}
/**ask yes or no **/
public static boolean askYesNo(String question) {
Scanner input = new Scanner(System.in);
String enteredText;
boolean isAnswerValid;
do{
isAnswerValid = false;
System.out.println(question);
enteredText = input.nextLine();
if (enteredText.length() > 0)
{
enteredText = enteredText.toUpperCase();
if(enteredText.equals("YES") || enteredText.equals("Y") || enteredText.equals("NO") || enteredText.equals("N"))
{
isAnswerValid = true;
}
}
if(isAnswerValid == false)
{
System.out.println("Please enter 'Yes' or 'No'?");
}
} while(isAnswerValid == false);
if(enteredText.equals("YES") || enteredText.equals("Y"))
{
return true;
}
return false;
}
}

If you can map a certain calculation scenario to a single structure, then the simple solution would be to use a class.
class InterestRateSource {
private Double firstFactor;
private Double secondFactor;
//etc
public InterestRateSource(Double firstFactor, Double secondFactor) {
this.firstFactor = firstFactor;
this.secondFactor = secondFactor;
};
public Double getFirstFactor() {
return this.firstFactor;
};
public Double getSecondFactor() {
return this.secondFactor;
};
};
// expand the above to account for all the variables of a single test case.
// Then simply use a List or whatever suitable collection.
List<InterestRateSource> myList = new ArrayList<InterestRateSource>();
myList.add(new InterestRateSource(5, 7));
myList.add(new InterestRateSource(3,4));
for (InterestRateSource currentRate: myList) {
// now you are iterating through the list. Do whatever calculations you need to do.
};

Related

Issue converting array to array list

Trying to write a java code for a single row Battleship style game, and when I tried to convert from an array to an ArrayList, the game started returning "miss" no matter what.
public class SimpleDotComGame {
public static void main(String[] args) {
int numofGuess = 0;
Scanner sc = new Scanner(System.in);
SimpleDotCom dot = new SimpleDotCom();
int ranNum = (int) (Math.random() * 5);
ArrayList<Integer> locations = new ArrayList<Integer>();
locations.add(ranNum);
locations.add(ranNum + 1);
locations.add(ranNum + 2);
dot.setLocationCells(locations); //think like you're running a
// separate program with parameters to set cells as "locations"
boolean isAlive = true;
while (isAlive == true) {
System.out.println("Enter a number");
String userGuess = sc.next();
String result = dot.checkYourself(userGuess); //run program to
// check if cells were hit by userGuess
numofGuess++;
if (result.equals("kill")) {
isAlive = false;
System.out.println("You took " + numofGuess + " guesses");
}
}
sc.close();
}
}
public class SimpleDotCom {
int numofHits = 0;
ArrayList<Integer> locationCells;
public void setLocationCells(ArrayList<Integer> locations) { //locations
// variable described array so we must define it as array now
locationCells = locations;
}
public String checkYourself(String userGuess) { //check using parameter userGuess
int guess = Integer.parseInt(userGuess);
String result = "miss";
int index = locationCells.indexOf(userGuess);
if (index >= 0) {
locationCells.remove(index);
if (locationCells.isEmpty()) {
result = "kill";
} else {
result = "hit";
}
}
System.out.println(result);
return result;
}
}
Change :
int index = locationCells.indexOf(userGuess);
to
int index = locationCells.indexOf(guess);
userGuess is a String which can not possibly be in a list of Integers. guess is an int which can.

Fraction calculator adding

Hi I'm new to java and am working on a Fraction calculator and I am unable to figure out how to get the calculator to reduce simple fractions and add mixed fractions.
Example:
Reduction: 1/2 + -5/6 = -1/3
Mixed Fractions: 4_15/16 + -3_11/16 = 1_1/4
Edit: For mixed fractions, I tried to subtract the numerator from the denominator for num>den to get the whole and the remainder and return it and print but it's not printing out anything.
import java.util.Scanner;
public class Fraction {
public static void main(String[] args) {
System.out.println("Enter an Expression or quit:");
Scanner input = new Scanner(System.in);
String text = input.nextLine();
while (!text.equals("quit")){
String frac1 = text.substring(0,text.indexOf(" "));
String oper = text.substring((text.indexOf(" "))+1,(text.indexOf(" "))+2);
String frac2 = text.substring((text.indexOf(" "))+3);
int fn1 = num(frac1); //frac1 numerator
int fd1 = den(frac1); //frac1 denominator
int fn2 = num(frac2); //frac2 numerator
int fd2 = den(frac2); //frac2 denominator
if (oper.equals("+")){
int sumfinalnum = add(fn1, fd1, fn2, fd2);
if (fd1 == 1 && fd2 == 1){
System.out.println(sumfinalnum);
}
else if ((fn1 + fn2)==0){
System.out.println("0");
}
else if (fd1 == fd2){
if (sumfinalnum>fd1){
System.out.println(extractWholePart(sumfinalnum,fd1)+"_"+extractNumPart(sumfinalnum,fd1)+"/"+fd1);
}
else{
System.out.println(sumfinalnum+"/"+fd1);
}
}
else if (!(fd1 == fd2)){
System.out.println(sumfinalnum+"/"+(fd1*fd2));
}
System.out.println("Enter an Expression or quit:");
text = input.nextLine();
}
}
}
public static int num(String input){
if (input.contains("_")){ //mixed to improper
String a = input.substring(0,input.indexOf("_"));
String b = input.substring((input.indexOf("_"))+1,input.indexOf("/"));
String c = input.substring((input.indexOf("/"))+1);
int a1 = Integer.parseInt(a);
int b1 = Integer.parseInt(b);
int c1 = Integer.parseInt(c);
int d = a1*c1;
int e = d+b1;
return e;
}
else if (!input.contains("/")){
int input1 = Integer.parseInt(input);
return input1;
}
else {
String strnum1 = input.substring(0,input.indexOf("/"));
int num1 = Integer.parseInt(strnum1);
return num1;
}
}
public static int den(String input){
if(!input.contains("/")) { //whole
return 1;
}
String strnum2 = input.substring((input.indexOf("/"))+1);
int num2 = Integer.parseInt(strnum2);
return num2;
}
public static int add(int fn1,int fd1,int fn2,int fd2){
if (fd1 == fd2){ //matching denominator
int numadd = fn1 + fn2;
return numadd;
}
else if (fd1 == 1 && fd2 == 1){ //whole numbers no denom
int sum = fn1 + fn2;
return sum;
}
else if (!(fd1 == fd2)){ //different denominator***
int dencomadd = fd1*fd2;
int gcd1 = dencomadd/fd1;
int gcd2 = dencomadd/fd2;
int comf1num = fn1*gcd1;
int comf2num = fn2*gcd2;
int total = comf1num+comf2num;
return total;
}
else{
return 0;
}
}
public static int extractWholePart(int finalnum, int finalden){
int whole = 0;
while (finalnum > finalden){
whole++;
}
return whole;
}
public static int extractNumPart(int finalnum, int finalden){
while (finalnum > finalden){
finalnum -= finalden;
}
return finalnum;
}
}
Let's start with - It's java, don't be afraid to use bigger variable names. fn1 could very well be called fraction1Numerator.
Next, have a single method to do what it's designed to do. Having an add method that needs four else-ifs in main is not a really good idea.
Creating an object Fraction that would have member variables numerator and denominator would allow your add function to return the entire answer. After all you have the code to add mixed fractions that looks good.
class Fraction{
public int whole;
public int numerator;
public int denominator;
}
I also added "whole" to indicate whole part after simplification. add function would than have signature
public static Fraction add(Fraction fraction1, Fraction fraction2) ...
Extracting whole numbers is simple - subtract denominator from numerator until you can't do that anymore.
public void extractWholePart(Fraction fraction){
int whole = 0;
while (fraction.numerator > fraction.denominator){
whole++;
fraction.numerator -= fraction.denominator;
}
fraction.whole = whole;
}
simplification on the other hand is just dividing both nominator and denominator by the greatest common divisor - algorythm for calculating that is easily findable on the internet.
Try something like this
float mixedToDecimal(String data)
// data would be like this "1 5/8";
String[] parts = data.split(" ");
if(!(parts.lenght > 0)) // this mean that if data is NOT mixedfraction then just return -1
return -1;
float value = Integer.parseInt(parts[0]);
if (parts.length > 1) {
// has fractional part
parts = parts[1].split("/");
float numerator = Integer.parseInt(parts[0]);
float denominator = Integer.parseInt(parts[1]);
value += numerator / denominator;
}
// value contains 1.625
return value;

Random variable generation in a Computation class

I am trying to run a class that performs calculations from data obtained from a random variable generator class. What I want is that 3 random variables be generated at any given time, then all calculation in that class be performed without another set of random variables be generated. Once all calculations have been performed then a new set of random variables can be generated. The Computation class is as shown below :
public class Computation {
public int meltTemp;
//public void mTemp;
public int mouldTemp;
public int setTemp;
public int Q;
public int volume;
public double Cp;
public int actualMouldTemp;
public double dT;
public int AMT ;//= Math.abs(dT);
public double mTemp;
public Hashtable catalogue1;
protected void setup() {
//create Hashtable
catalogue1 = new Hashtable();
}
public double getAnswer() {
int rand1[] = new int[3];
int input [] = new int [2];
ControlGUI par = new ControlGUI ();
//input = ControlGUI.getArray();
//catalogue am = new catalogue();
RandomVariableGenerator var = new RandomVariableGenerator();
rand1 = RandomVariableGenerator.getRand();
//int rand[] = Arrays.copyOf(rand1, rand1.length);
meltTemp = 245;
System.out.println("Melt Temp is : "+ meltTemp);
actualMouldTemp = (int) ((0 - 51.4)+(0.302 * meltTemp) +(1.64 * rand1[0])+(0.201 * rand1[1]));
System.out.println("The actual mould temperature is :" +actualMouldTemp + " Degrees celcius" );
return actualMouldTemp;
}
public int getDiff(){
Computation amg = new Computation();
double result[] = new double [4]; {
setTemp = 55;
dT = (actualMouldTemp - setTemp);
AMT = (int) Math.abs(dT);
System.out.println("The temperature difference is : "+ AMT);
return AMT;
}
}
The next method to try and use the generated variables is getHeatingTime1() which needs rand1[2] for the tank volume:
public double getHeatingTime1(){
Computation jose = new Computation();
int [] Results = new int [4];
Results [0] = AMT;
//Results [] = Computation.class;
Q = 3; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
//AMT =
System.out.println("AMT IS "+ Results [0]);
long HT1 = (long) ((volume*Cp*Results [0])/Q);
return HT1;
}
public double getHeatingTime2(){
int Results [] = new int [4] ;
Computation cr7 = new Computation();
//double dT = cr7.getDiff();
Q = 9; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
//AMT = 7;
System.out.println("AMT IS "+ Results [1]);
long HT2 = (long) ((volume*Cp*Results [1])/Q);
return HT2;
}
public double getHeatingTime3(){
int Results [] = new int [4];
//double AMT = getDiff();
Computation jt = new Computation();
//double dT = jt.getDiff();
// AMT = 7;
Q = 18; //heating in kW
Cp = 4.2; //Specific heat capacity of water
volume = 6;
System.out.println("AMT IS "+ Results [1]);
long HT3 = (long) ((volume*Cp*Results [1])/Q);
return HT3;
}
public double getCoolingTime(){
// double CT = 0;
Computation nvh = new Computation();
int rand1[] = new int[3];
int rand[] = Arrays.copyOf(rand1, rand1.length);
//RandomVariableGenerator var = new RandomVariableGenerator();
//rand1 = Computation;
mouldTemp = 55;
System.out.println("Rand 0 is "+ rand1[0]);
System.out.println("Rand 1 is "+ rand1[1]);
System.out.println("Rand 2 is "+ rand1[2]);
double CT = ((0.5/rand[2])*((mouldTemp - rand1[0])/(rand1[1] - mouldTemp)));
double CTA = Math.abs(CT);
return CTA;
}
}
The Random variable generator class is as shown below:
public class RandomVariableGenerator {
public static int[] getRand (){
int rand[] = new int [3];
Random r = new Random ();
int myRandomNumber = 0;
//for (int i=0; i < 1 ; i++)
myRandomNumber = r.nextInt(15) + 5;
System.out.println("Chilled water temperature:" + myRandomNumber);
rand[0] = myRandomNumber;
Random rn = new Random ();
int myNumber = 0;
// (for int i=0; i < 1; i++)
myNumber = rn.nextInt(25) + 50;
System.out.println("Heated water temperature:" + myNumber);
rand[1]= myNumber;
Random rm = new Random ();
int myRandNumber = 0;
// (for int i=0; i < 1; i++)
myRandNumber = rm.nextInt(2) + 6;
System.out.println("Tank Volume:" + myRandNumber);
rand[2]= myRandNumber;
return rand;
}
}
Declare an instance int vector to hold the three values at object (instance) level (rndVars[3])
public class Computation {
public int meltTemp;
//public void mTemp;
public int mouldTemp;
public int setTemp;
public int Q;
public int volume;
public double Cp;
public int actualMouldTemp;
public double dT;
public int AMT ;//= Math.abs(dT);
public double mTemp;
private int [] rndVars = new int[3];
...
Have a public method setRandomVars() you can call whenever you need the 3 values to be reset.
public void setRandomVars(){
rndVars[0] = RandomVariableGenerator.getRand();
rndVars[1] = RandomVariableGenerator.getRand();
rndVars[2] = RandomVariableGenerator.getRand();
}
You could make all of the 3 random variables private and to the class, not the function. Then, when you need a new set call a function that resets them.
For example:
public class MyClass{
//replace these with the actual types/variables you need
int var1;
double var2;
double var3;
/**
*Call this function when you need a new set of variables
**/
public void resetVariables(){
//Change this to the random class you would prefer to use
Random random = new Random(System.currentTimeMillis());
var1 = random.nextInt();
var2 = random.nextDouble();
var3 = random.nextDouble();
}
//put your other functions here except remove the declarations for var1, var2, and var3
/*
ex.
public int myFunction(){
Random random = new Random(System.currentTimeMillis());
int var1 = random.nextInt();
return var1 * 2;
}
becomes
public int myFunction(){
// use the global variable instead of the function's variable
return var1 * 2;
}
*/
}

IndexOutOfBoundsException while accessing List

I'm working on a project for a class, and I think I've got it mostly figured out, but it keeps giving me different Exception errors and now I'm stumped.
The instructions can be found here: http://www.cse.ohio-state.edu/cse1223/currentsem/projects/CSE1223Project11.html
Here is the code I have thus far, currently giving me and IndexOutOfBounds exception in the getMaximum method.
Any help would be much appreciated.
import java.io.*;
import java.util.*;
public class Project11a {
public static void main(String[] args) throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter an input file name: ");
String fileName = keyboard.nextLine();
Scanner in = new Scanner(new File(fileName));
System.out.print("Enter an output file name: ");
String outFile = keyboard.nextLine();
PrintWriter outputFile = new PrintWriter(outFile);
while (in.hasNextLine()) {
String name = in.nextLine();
List<Integer> series = readNextSeries(in);
int mean = getAverage(series);
int median = getMedian(series);
int max = getMaximum(series);
int min = getMinimum(series);
outputFile.printf("%-22s%6d%n", name, mean, median, max, min);
}
in.close();
outputFile.close();
}
// Given a Scanner as input read in a list of integers one at a time until a
// negative
// value is read from the Scanner. Store these integers in an
// ArrayList<Integer> and
// return the ArrayList<Integer> to the calling program.
private static List<Integer> readNextSeries(Scanner inScanner) {
List<Integer> nextSeries = new ArrayList<Integer>();
while (inScanner.hasNextInt()) {
int currentLine = inScanner.nextInt();
if (currentLine != -1) {
nextSeries.add(currentLine);
} else {
break;
}
}
return nextSeries;
}
// Given a List<Integer> of integers, compute the median of the list and
// return it to
// the calling program.
private static int getMedian(List<Integer> inList) {
Collections.sort(inList);
int middle = inList.size() / 2;
int median = -1;
if (inList.size() % 2 == 1) {
median = inList.get(middle);
} else {
try {
median = (inList.get(middle - 1) + inList.get(middle)) / 2;
} catch (Exception e) {
}
}
return median;
}
// Given a List<Integer> of integers, compute the average of the list and
// return it to
// the calling program.
private static int getAverage(List<Integer> inList) {
int average = 0;
if (inList.size() == 0) {
return 0;
}
for (int i = 0; i < inList.size(); i++) {
average += inList.get(i);
}
return (average / inList.size());
}
// Given a List<Integer> of integers, compute the maximum of the list and
// return it to
// the calling program.
private static int getMaximum(List<Integer> inList) {
int max = inList.get(0);
for (int i = 1; i < inList.size(); i++) {
if (inList.get(i) > max) {
max = inList.get(i);
}
}
return max;
}
// Given a List<Integer> of integers, compute the maximum of the list and
// return it to
// the calling program.
private static int getMinimum(List<Integer> inList) {
int min = inList.get(0);
for (int i = 1; i < inList.size(); i++) {
if (inList.get(i) < min) {
min = inList.get(i);
}
}
return min;
}
}
Seemed like that your list is empty.
What can triggered the exception is the statement:
int max = inList.get(0);
So your inList do not have the value in the first index,which means the inList is empty.

Sorting of two-dimensional array based on two parameters

The following code performs 'hierarchical' sorting of a two-dimensional matrix. Firstly, it sorts elements based on the values of ranks. Secondly, it takes this sorted matrix, searches elements that have the same values of ranks, and sorts them based on dist. In descending order.
Question 1: Is it possible to achieve the same result in the easier way? I tried to create a Comparator, but it provided incorrect result for this particular case.
Question 2: How to get indexes of unsorted elements after sorting?
import java.util.ArrayList;
public class Test {
public static void main(String args[]) {
ArrayList<ArrayList<Double>> values = new ArrayList<ArrayList<Double>>();
ArrayList<Double> ranks = new ArrayList<Double>();
ArrayList<Double> dist = new ArrayList<Double>();
ranks.add(8.0);
ranks.add(3.0);
ranks.add(8.0);
ranks.add(1.0);
dist.add(1.8);
dist.add(2.8);
dist.add(1.9);
dist.add(2.1);
values.add(0,ranks);
values.add(1,dist);
int len = ranks.size();
ArrayList<ArrayList<Double>> sortedranks = new ArrayList<ArrayList<Double>>();
sortedranks = order(values,0,ranks.size());
boolean swapped = true;
int j = 0;
double tmp1, tmp2;
while (swapped) {
swapped = false;
j++;
for (int i = 0; i < len - j; i++) {
double val1 = sortedranks.get(0).get(i);
double val2 = sortedranks.get(0).get(i+1);
if (val1==val2) {
if (sortedranks.get(1).get(i) < sortedranks.get(1).get(i+1)) {
tmp1 = sortedranks.get(1).get(i);
tmp2 = sortedranks.get(1).get(i+1);
sortedranks.get(1).remove(i);
sortedranks.get(1).remove(i);
sortedranks.get(1).add(i,tmp2);
sortedranks.get(1).add(i+1,tmp1);
swapped = true;
}
}
}
}
for (int i = 0; i < len; i++) {
System.out.println("Ranks " + i + " : " + sortedranks.get(0).get(i)
+ ", Distances : " + sortedranks.get(1).get(i));
}
}
public static ArrayList<ArrayList<Double>> order(ArrayList<ArrayList<Double>> values, int i_start, int i_fin) {
boolean swapped = true;
int j = 0;
int i_rank = 0;
int i_dist = 1;
double tmp1_rank, tmp2_rank, tmp1_dist, tmp2_dist;
while (swapped) {
swapped = false;
j++;
for (int i = i_start; i < i_fin - j; i++) {
if (values.get(i_rank).get(i) < values.get(i_rank).get(i+1)) {
tmp1_rank = values.get(i_rank).get(i);
tmp2_rank = values.get(i_rank).get(i+1);
tmp1_dist = values.get(i_dist).get(i);
tmp2_dist = values.get(i_dist).get(i+1);
values.get(i_rank).remove(i);
values.get(i_rank).remove(i);
values.get(i_dist).remove(i);
values.get(i_dist).remove(i);
values.get(i_rank).add(i,tmp2_rank);
values.get(i_rank).add(i+1,tmp1_rank);
values.get(i_dist).add(i,tmp2_dist);
values.get(i_dist).add(i+1,tmp1_dist);
swapped = true;
}
}
}
return values;
}
}
The code that uses Comparator (does not work for my case):
public class MyEntry implements Comparable<MyEntry> {
private Double rank;
private Double dist;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
}
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
Double rfirst = value1.rank;
Double rsecond = value2.rank;
Double dfirst = value1.dist;
Double dsecond = value2.dist;
if (rsecond != rfirst) {
return (int) (rsecond - rfirst);
}
else {
return (int) (dsecond - dfirst);
}
}
};
}
Your Comperator approach would work, but is has a few bugs.
First of all I would replace the Doubles in MyEntry by double.
Comparing Double is not the same as comparing double
For example:
Double a = 1.0;
Double b = 1.0;
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.doubleValue()== b.doubleValue());
Will return
false
true
true
Then in the comparison you cast to int, but this implies flooring that data.
(int) (2 - 1.9) will give 0
Better is to compare using < and return -1 or 1.
public static Comparator<MyEntry> ValueComparator = new Comparator<MyEntry>() {
public int compare(MyEntry value1, MyEntry value2) {
double rfirst = value1.rank;
double rsecond = value2.rank;
double dfirst = value1.dist;
double dsecond = value2.dist;
if (rsecond != rfirst) {
return rsecond < rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond < dfirst ?-1:1;
}
return 0;
}
}
For your second question you require an index. This could be done in two ways. First option is to include the index in MyEntry like this:
public class MyEntry implements Comparable<MyEntry> {
private double rank;
private double dist;
private int index;
private static int nextIndex = 0;
public MyEntry(double rank, double dist) {
this.rank = rank;
this.dist = dist;
this.index = nextIndex++;
}
This way you will be able to retain the index but it is not so flexible.
A more flexible approach could be to have the index in a separate array, and sort that.
class IndexedArrayComparator implements Comparator<Integer>{
MyEntry[] array;
public IndexedArrayComparator(MyEntry[] entries){
this.array=entries;
}
public Integer[] createIndexes(){
Integer[] index = new Integer[array.length];
for(int i =0;i<index.length;i++){
index[i]=i;
}
return index;
}
public int compare(Integer i0, Integer i1) {
double rfirst = array[i0].rank;
double rsecond = array[i1].rank;
double dfirst = array[i0].dist;
double dsecond = array[i1].dist;
if (rsecond != rfirst) {
return rsecond > rfirst?-1:1;
}
else if(dsecond!=dfirst){
return dsecond > dfirst ?-1:1;
}
return 0;
}
}
You can then use it like this:
MyEntry[] entries = new MyEntry[5];
entries[0]= new MyEntry(1.1,5);
entries[1]= new MyEntry(1.1,4);
entries[2]= new MyEntry(2.1,5);
entries[3]= new MyEntry(0.1,3);
entries[4]= new MyEntry(3.1,1);
IndexedArrayComparator comp = new IndexedArrayComparator(entries);
Integer[] index = comp.createIndexes();
Arrays.sort(index,comp);
for(int i =0;i<index.length;i++){
MyEntry e = entries[index[i]];
System.out.println(String.format("%2d:r= %3.1f, d= %3.1f" ,index[i],e.rank,e.dist));
}
Which will give:
3:r= 0.1, d= 3.0
1:r= 1.1, d= 4.0
0:r= 1.1, d= 5.0
2:r= 2.1, d= 5.0
4:r= 3.1, d= 1.0
The second way of sorting while maintaining the index is also described here. Credits to Jon Skeet

Categories