I am trying to find and print the number of occurrences of fractions from a file in my program. Fractions that simplify down to the same number counts as an occurrence, so 12/6 counts for 6/3 as well. So far, I have separated the fractions into numerator and denominator in separate arrays. The fractions I have in the numerator and denominator came from a separate array that I received from a file. I am having trouble trying to figure out how to simplify the fractions and also find the total occurrence of them. This is what I have so far:
String[] split = new String[2]; //String that holds numerator and denominator
int[] numerator = new int[100];
int[] denominator = new int[100];
for(int i = 0; i < numOfFractions; i) { //Loop through # of Lines
split = fractions[i].split("/"); //Split the fractions at the /
System.out.println("Test here " fractions[i]); //TODO --> test
numerator[i] = Integer.parseInt(split[0]); //Numerator
System.out.println("Numerator = " numerator[i]); //TODO --> test
denominator[i] = Integer.parseInt(split[1]); //Denominator
System.out.println("Denominator = " denominator[i] "\n"); //TODO --> test
}
}
I have added some tests within my method to make sure everything is working properly, which it seems so far it is. I would like to also note I do not know how to use HashMap and ArrayList and would prefer staying within on class.
These are the fractions obtained from a file. Each fraction is on its own line, and can assume every fraction will be (A/B) format
6/3
4/2
5/9
80/90
800/900
15/25
5/5
1/1
1/10
1/100
1/1000
1/3
2/6
1/2
1/3
1/1
1/4
1/5
1/6
1/7
1/8
1/9
2/1
2/2
2/3
2/4
2/5
2/6
2/7
2/8
2/9
CodePudding user response:
You can reduce them by finding the greatest common divisor of the numerator and the denominator. You can do it like so.
public static int gcd(int r, int s) {
while (s > 0) {
int t = r % s;
r = s;
s = t;
}
return r;
}
for 27/12
int d = gcd(27,12); // returns 3
27/3 = 9
12/3 = 4
so the reduced fraction is 9/4. So every equal fraction will reduce to the same value when the numerator and denominator are divided by the GCD of those numbers.
It uses Euclid's Algorithm
Here is how it might be applied in your case.
- create a map to hold the reduced fraction as key and an Integer for the count.
- then convert the fraction to a numeric value and divide by the GCD
- then store the reduced fraction as a string key and increment the count for that key.
String[] s = {"10/2", "27/3", "19/4", "15/3", "12/4", "3/5", "9/15"};
Map<String, Integer> fractions = new HashMap<>();
String[] s = { "10/2", "27/3", "19/4", "15/3", "12/4", "3/5",
"9/15" };
for (String vv : s) {
String[] nd = vv.split("/");
int n = Integer.parseInt(nd[0]);
int d = Integer.parseInt(nd[1]);
int div = gcd(n, d);
n /= div;
d /= div;
String reduced = String.format("%d/%d", n, d);
fractions.compute(reduced, (k,v)->v == null ? 1 : v 1);
}
fractions.entrySet().forEach(System.out::println);
}
prints
3/1=1
5/1=2
3/5=2
19/4=1
9/1=1
Note. What
fractions.compute(reduced, (k,v)->v == null ? 1 : v 1);
does is to check if the value is null. If so, set the count to 1, otherwise add 1 to the existing count.
CodePudding user response:
I would create a Fraction class as below. I would override equals() and hashCode() methods, so I can use this class with Map.
public class Fraction {
int nominator;
int denominator;
public Fraction(int nominator, int denominator) {
this.nominator = nominator;
this.denominator = denominator;
}
/**
* The method checks if two fractions are equal.
* Example 1: Fraction 1 is 5/3 and Fraction 2 is 7/4.
* The method checks if 5X4 == 7X3 and returns false.
* Example 2: Fraction 1 is 12/6 and Fraction 2 is 8/4.
* The method checks 12X4 == 8X6 and returns true.
* @param obj
* @return
*/
@Override
public boolean equals(Object obj){
if(obj.getClass() != this.getClass()){
return false;
}
Fraction f = (Fraction)obj;
int nominator1 = this.getNominator();
int nominator2 = f.getNominator();
int denominator1 = this.getDenominator();
int denominator2 = this.getDenominator();
nominator1 = nominator1 * denominator2;
nominator2 = nominator2 * denominator1;
return nominator1 == nominator2;
}
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash this.nominator;
hash = 97 * hash this.denominator;
return hash;
}
public int getNominator() {
return nominator;
}
public int getDenominator() {
return denominator;
}
}
Then, I would create Fraction objects from your data input file. I understand you already have retrieved integer values of nominators and denominators. The following code creates a new Fraction object and adds it into the list.
List<Fraction> fractions = new ArrayList<>();
Fraction fr = new Fraction(1, 2);
fractions.add(fr);
Once you populate the list with your input data, you can use a Map to find and print the result.
Map<Fraction,Integer> map = new HashMap<>();
for(Fraction f: fractions){
if(map.containsKey(f)){
int value = map.get(f);
value ;
map.put(f, value);
} else {
map.put(f, 1);
}
}
System.out.println(map);
