1

I recently made a very simple practice program in Python, that takes user input and rolls dice. The code is:

import random
import sys
import math

def roll(rolls, sides, results):
    for rolls in range(1, rolls + 1):
        result = random.randrange(1, sides + 1)
        print result
        results.append(result)
def countf(rolls, sides, results):
    i = 1
    print "There were", rolls, "rolls."
    for sides in range(1, sides + 1):
        if results.count(i) != 1:
            print "There were", results.count(i), i,"s."
        else:
            print "There was", results.count(i), i
        i = i + 1
        if i == sides:
            break
    rolls = input("How many rolls? ")
        sides = input("How many sides of the die? ")
        results = []

        roll(rolls, sides, results)
        countf(rolls, sides, results)

(actually this is part of a larger program, so I had to cut'n'paste bits, and I might have missed something out).

And so I decided to translate that to Java. Notice the algorithm here: get random number, print it, append it to an array, then count the amount of each number in the array at the end, and print out that value. Problem is, I don't know how to do the equivalent of someArray.count(someIndex) in Java syntax. So my Java program looks like this so far:

import java.util.*;

public class Dice {
    static Scanner input = new Scanner(System.in);
    public static void main(String[] args) {
        final static int TIMES_TO_ROLL = getInt("Times to roll?");
        Random flip = new Random();
        int[] results = new int[TIMES_TO_ROLL];
        for (int i = 0; i < TIMES_TO_ROLL; i++) {
            int result = flip.nextInt(6);
            System.out.println(result);
            results[i] = result;
        }
    }
    public static int getInt(String prompt) {
        System.out.print(prompt + " ");
        int integer = input.nextInt();
        input.nextLine();
        return integer;
    }
}

So can someone help me with the array counting code? I understand that this might not be a defined method, since Python is higher level after all, so I could make my own array counting method, but I was wondering if Java, like Python, has a predefined one.

EDIT: I managed something like this:

public static int arrayCount(int[] array, int item) {
    int amt = 0;
    for (int i = 0; i < array.length; i++) {
        if (array[i] == item) {
            amt++;
        }
        else {
            amt = amt;
        }
    }
    return amt;
}

EDIT: Just out of interest, assuming I use Command prompt to run my Java program and Python.exe (command prompt console for Python), which one will be faster (in other words, for the same code, which language has better performance?)?

Bluefire
  • 13,519
  • 24
  • 74
  • 118
  • http://stackoverflow.com/questions/1217228/what-is-the-java-equivalent-for-linq SOme suggestion on how to query objects in Java.. dont have objects? oops. then make some – Piotr Kula Jun 15 '12 at 15:33

6 Answers6

7

You could use a HashMap to store the result.

If the new number is not in your map you add it with "1" as initial value. If it exists your put "+1" to the current map value.

To display the values you just have to iterate on you entries in a for each loop.

jocelyn
  • 788
  • 6
  • 12
  • 2
    Judging by my reputation, you should have seen this coming: what's a HashMap? – Bluefire Jun 15 '12 at 15:37
  • 1
    you could use that, or your Collections.frecuency like someone suggested here (less code) – AlbertFerras Jun 15 '12 at 15:40
  • As I said in the other response, Collections.frequency is bad if you need the information on all your collection because collections.frequency does a full scann of your collection on each call ! HashMap is basicly a key value store system. You want to store some information and access it directy by it's key. see : http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html – jocelyn Jun 15 '12 at 15:44
6

The solution is to transform your array to a List and then use the Collections.frequency method:

List<Integer> resultList = Arrays.asList(results);
int freq = Collections.frequency(resultList, 4);

Also you could use ArrayList from the very beginning saving you the transformation:

List<Integer> result = new ArrayList<Integer>();
// add results
int freq = Collections.frequency(result, 4);

See the Collections documentation here

EDIT: If performance is an issue (as suggested in the comments) then maybe you want to use each index of the array as a counter, as follows:

    Random flip = new Random(SIDES);
    int[] counters = new int[SIDES];
    for (int i = 0; i < TIMES_TO_ROLL; i++) {
        int result = flip.nextInt;
        counters[result] = counters[result]+1;
    }

Notice that you no longer need to count at the end since you've already got all the counters in the array and there is no overhead of calculating the hash.

jspboix
  • 766
  • 1
  • 4
  • 8
  • Collections.frequency does a full collection loop on each call. Because he wants the information on every elements of his collection this wont be efficient at all. – jocelyn Jun 15 '12 at 15:41
  • The script in python also does the full scan every time by calling `results.count` so I assumed that performance was not an issue in this case. Performance wise it would be much better to have an array where each index represents the dice side and the value is the number of occurrences. – jspboix Jun 15 '12 at 15:50
3

There are a couple libraries that will do this for you:

  1. Google Guava's MultiSet
  2. Apache Common's Bag

But for something so simple, you may consider an extra library a bit excessive.

You can also do this yourself with an int[]. Assuming your dice is using whole numbers, have the number rolled refer to the index into the array, and then increment the value at that index. When you need to retrieve the value for a given number, look up its value by the index.

private static final int NUMBER_DICE_SIDES = 6;
public static void main(String[] args) {
    final static int TIMES_TO_ROLL = getInt("Times to roll?");
    Random flip = new Random(NUMBER_DICE_SIDES);
    int[] results = new int[NUMBER_DICE_SIDES];
    for (int i = 0; i < TIMES_TO_ROLL; i++) {
        int result = flip.nextInt;
        System.out.println(result);
        results[result]++;
    }

    for(int i = 0; i < NUMBER_DICE_SIDES; ++i) {
        System.out.println((i+1)+"'s: " + arraysCount(results, i));
    }
}

public static int arrayCount(int[] array, int item) {
    return array[item];
}
nicholas.hauschild
  • 42,483
  • 9
  • 127
  • 120
  • Found it - https://commons.apache.org/proper/commons-collections/javadocs/api-2.1.1/org/apache/commons/collections/Bag.html – jesses.co.tt Sep 18 '15 at 02:38
3

There's a frequency method in collections

 int occurrences = Collections.frequency(listObject, searchItem);

Java doc for collections

YYZ
  • 749
  • 4
  • 8
  • 18
1

As far as I am aware, there is no defined method to return the frequency of a particular element in an array. If you were to write a custom method, it would simply be a matter of iterating through the array, checking each value, and if the value matches the element you're after, incrementing a counter.

So something like:

// in this example, we assume myArray is an array of ints
private int count( int[] myArray, int targetValue) {
    int counter = 0;
    for (int i = 0 ; i < myArray.length; i++ ) {
        if (myArray[i] == targetValue) {
            counter++;
        }
    }
    return counter;
}

Of course, if you want to find the frequency of all the unique values in your array, this has the potential of being extremely inefficient.

Also, why are you using a 7-sided die? The Random nextInt() will return a number from 0 up to but not including the max. So your die will return values from 0 through 6. For a six-sided die, you'd want a new Random(6); and then increment your roll by one to get a value from one through six: flip.nextInt() +1;.

Roddy of the Frozen Peas
  • 14,380
  • 9
  • 49
  • 99
  • Does it matter if the method is private or public (I edited the post and put in a method I made, but it's public :O)? – Bluefire Jun 15 '12 at 15:37
  • Wow, you made yours totally independently from mine and they're exactly the same (apart from variable names and the fact that yours is private). – Bluefire Jun 15 '12 at 15:39
  • Also, about using a 7 sided die - oops, that's Python syntax :D – Bluefire Jun 15 '12 at 15:43
  • @Bluefire `public` versus `private` just indicates the scope of the method. If it's private, it can only be called within the class itself. If it's public, anyone call call that method on that object. – Roddy of the Frozen Peas Jun 15 '12 at 16:28
0
class FindOccurrence {


  public static void main (String[]args) {

    int myArray[] = {5, 8, 5, 12, 19, 5, 6, 7, 100, 5, 45, 6, 5, 5, 5};
    int numToFind = 5;
    int numberOfOccurrence = 0;

    for (int i=0; i < myArray.length; i++) {

        if (numToFind == myArray[i]) { 
            numberOfOccurrence++;

        }

    }
    System.out.println("Our number: " + numToFind);
    System.out.println("Number of times it appears: " + numberOfOccurrence);
}
}
Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132