I'm writing a program that counts the occurrences of integers entered into an array, eg if you entered 1 1 1 1 2 1 3 5 2 3, the program would print out the distinct numbers followed by their occurrences, like this:
1 occurs 5 times, 2 occurs 2 times, 3 occurs 2 times, 5 occurs 1 time
And it's almost finished, aside from one problem I can't figure out:
import java.util.Scanner;
import java.util.Arrays;
public class CountOccurrences
{
public static void main (String [] args)
{
Scanner scan = new Scanner (System.in);
final int MAX_NUM = 10;
final int MAX_VALUE = 100;
int [] numList;
int num;
int numCount;
int [] occurrences;
int count[];
String end;
numList = new int [MAX_NUM];
occurrences = new int [MAX_NUM];
count = new int [MAX_NUM];
do
{
System.out.print ("Enter 10 integers between 1 and 100: ");
for (num = 0; num < MAX_NUM; num++)
{
numList[num] = scan.nextInt();
}
Arrays.sort(numList);
count = occurrences (numList);
System.out.println();
for (num = 0; num < MAX_NUM; num++)
{
if (num == 0)
{
if (count[num] <= 1)
System.out.println (numList[num] + " occurs " + count[num] + " time");
if (count[num] > 1)
System.out.println (numList[num] + " occurs " + count[num] + " times");
}
if (num > 0 && numList[num] != numList[num - 1])
{
if (count[num] <= 1)
System.out.println (numList[num] + " occurs " + count[num] + " time");
if (count[num] > 1)
System.out.println (numList[num] + " occurs " + count[num] + " times");
}
}
System.out.print ("\nContinue? <y/n> ");
end = scan.next();
} while (!end.equalsIgnoreCase("n"));
}
public static int [] occurrences (int [] list)
{
final int MAX_VALUE = 100;
int num;
int [] countNum = new int [MAX_VALUE];
int [] counts = new int [MAX_VALUE];
for (num = 0; num < list.length; num++)
{
counts[num] = countNum[list[num]] += 1;
}
return counts;
}
}
The problem I'm having is that no matter what the current value for 'num' is, 'count' only prints out 1, and the problem isn't in the method that counts the occurrences, because when you enter numbers in the place of the variable, the value changes.
Is there any way that I can alter this so that it'll print out the occurrences properly, or should I try something else? And the simpler the solution, the better, as I haven't yet gone past single dimension arrays.
Thanks for the help!
Try HashMap. For this type of problem hashes is very efficient and fast.
I write this function which take array and return a HashMap whose key is the number and value is the occurance of that number.
public static HashMap<Integer, Integer> getRepetitions(int[] testCases) {
HashMap<Integer, Integer> numberAppearance = new HashMap<Integer, Integer>();
for(int n: testCases) {
if(numberAppearance.containsKey(n)) {
int counter = numberAppearance.get(n);
counter = counter+1;
numberAppearance.put(n, counter);
} else {
numberAppearance.put(n, 1);
}
}
return numberAppearance;
}
Now iterate throught hashmap and print occurance of numbers like this :
HashMap<Integer, Integer> table = getRepetitions(testCases);
for (int key: table.keySet()) {
System.out.println(key + " occur " + table.get(key) + " times");
}
Output:
I'd use a Bag, a collection that counts the number of times an item appears in the collection. Apache Commons has an implementation of it. Here's their interface, and here's a sorted tree implementation.
You'd do something like this:
Bag<Integer> bag = new TreeBag<Integer>();
for (int i = 0; i < numList.length; i++) {
bag.add(numList[i]);
}
for (int uniqueNumber: bag.uniqueSet()) {
System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}
The example above takes elements from your numList
array and adds them to the Bag
for purposes of generating the counts, but de rigueur you don't even need the array. Just add the elements to the Bag
directly. Something like:
// Make your bag.
Bag<Integer> bag = new TreeBag<Integer>();
...
// Populate your bag.
for (num = 0; num < MAX_NUM; num++) {
bag.add(scan.nextInt());
}
...
// Print the counts for each unique item in your bag.
for (int uniqueNumber: bag.uniqueSet()) {
System.out.println("Number " + uniqueNumber + " counted " + bag.getCount(uniqueNumber) + " times");
}
What I have to say is, it took me a while to figure out what the two variables count
and countNum
represent for, maybe some comments are needed. But finally I find out the bug.
Suppose input ten numbers are: 5, 6, 7, 8, 5, 6, 7, 8, 5, 6
After sort, numList
is : 5, 5, 5, 6, 6, 6, 7, 7, 8, 8
The array count
returned by occurrences()
should be: [1, 2, 3, 1, 2, 3, 1, 2, 1, 2]
Actually the only useful numbers in this result array are:
count[2]: 3 count number for numList[2]: 5
count[5]: 3 count number for numList[5]: 6
count[7]: 2 count number for numList[7]: 7
count[9]: 2 count number for numList[9]: 8
The other numbers, like the first two numbers 1, 2
before 3
, are only used to calculate the sum occurrences incrementally, right? So, your loop logic should be changed as following:
remove the first if
code block:
if (num == 0)
{
if (count[num] <= 1)
System.out.println (numList[num] + " occurs " + count[num] + " time");
if (count[num] > 1)
System.out.println (numList[num] + " occurs " + count[num] + " times");
}
Change the second if
condition to:
if ((num + 1) == MAX_NUM || numList[num] != numList[num + 1]) {
......
}
After this, your code should work well as expected.
BTW, you really don't need to do it so intricately. Just try HashMap
:)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With