Counting instances of a value in an array - java

Homework. Dice Game. I've got an array that represents five rolls of a die. Consider:
diceRoll[] = {6,3,3,4,5}. I would LIKE to create a SECOND array that has the counts of values from one to six contained in diceRoll[], (e.g., occurence[] = {0,0,2,1,1,1} for the diceRoll[] above.) but I fear I'm getting lost in nested loops and can't seem to figure out which value I ~should~ be returning. occurence[] is a global variable, and the intent is that the array will contain six values...the count of ones (at index [0]), twos (at [1]), threes (at [2]), etc.
So Far:
for(i=1;i<7;i++) /* die values 1 - 6
{
for(j=0;j<diceRoll.length;j++) /* number of dice
{
if (diceRoll[j] == i) /* increment occurences when die[j] equals 1, then 2, etc.
occurence = occurence + 1;
}
}
return occurence;
}
I cannot, however, get the occurence=occurence+1 to work. bad operand types for binary operator is my most common error. I suspect I need to increment occurence OUTSIDE one or both of the for loops, but I'm lost.
Guidance? or perhaps the one-line easy way to do this?
d

The easiest way I have to do this is to create the second array in order so that
occurrence[0] = # of 1's occurrence[1] = # of 2's and so on. Then this becomes a 1 loop method.
//method to return number of occurrences of the numbers in diceRolls
int[] countOccurrences(int[] diceRolls) {
int occurrence[] = new int[6]; //to hold the counts
for(int i = 0; i < diceRolls.length; i++) { //Loop over the dice rolls array
int value = diceRolls[i]; //Get the value of the next roll
occurence[value]++; //Increment the value in the count array this is equivalent to occurrence[value] = occurrence[value] + 1;
//occurrence[diceRolls[i]]++; I broke this into two lines for explanation purposes
}
return occurrence; //return the counts
}
EDIT:
Then to get the count for any particular value use occurrence[value-1]

Related

After generating an array, how to filter out specific numbers I need?

I have an assignment that I can´t solve for a couple of days. I am very frustrated and feel too dumb for java. The Problem is the extract of the code below (my Professor wrote it). My task is to complete the code. So that when I write in my terminal for example "java Yahtzee 1 1 1 2 3" I should receive "sum of ones: 3".
Why did I stick to this problem? - because I don´t really understand these brackets [i] and how to deal with them.
import java.util.Arrays;
public class Yahtzee {
/**
* ones
* #param dice rolled numbers, sorted in ascending order
* #return the sum of the numbers on all dice showing a 1
*/
private static int aces(int[] dice) {
return -1;
}
public static void main(String[] args) {
// it is allowed to change the main method
if(args.length != 5) {
// the array length should be 5
System.out.println("ERROR: nicht genau 5 Zahlen übergeben");
return;
}
// read the passed numbers
int[] dice = new int[args.length];
for(int i = 0; i < args.length; i++) {
dice[i] = Integer.parseInt(args[i]);
if(dice[i] < 1 || dice[i] > 6) {
System.out.println("Error: invalid number " + dice[i]);
return;
}
}
System.out.println("sum of ones: " + aces(dice));
}
}
I think I should filter out the three ones. My first thought is to make an if-statement in main-method that could look like this: if(dice[i] == 1) and find only those ones. But I dont have idea how to work further. Can some one explain how to solve this problem or give an idea?
I started first programming 1 month ago and learned already some about loops and booleans and arrays. I red other questions like mine, but I do not understand what they do (I only worked with integers and doubles). I think I should work with loops or something like that.
To begin with, it's helpful to know how Yahtzee is played and this link. As you can see in the links, the game of Yahtzee is played with five dice which a player rolls. The value of each dice is held within a int[] Array as an integer element value:
Knowing this and once the dice array is filled, you can iterate through the dice[] Array and sum whatever you like within the aces() method. Obviously, because the method is named aces, it would be any dice[] element that has a value of 1 that is summed, for example:
private static int aces(int[] dice) {
int sum = 0;
/* Read each element of the supplied dice[] Array...
We start `i` at 0 because the first element in any
array is at index 0 (not 1) and we will iterate
through until we reach the array length which is
a literal value. There is no index 5 which is why
it will keep looping for as long as `i` is less
than (<) dice.length. */
for (int i = 0; i < dice.length; i++) {
// Does the current array element contain a value of 1?
if (dice[i] == 1) {
//Yes ... then sum it
sum += dice[i]; // Same as: sum = sum + {value in dice[i] (which is 1)}
}
// No...continue looping.
}
/*
// Can also be done this way with an Enhanced `for` loop:
for (int v : dice) {
if (v == 1) { sum += v; }
}
*/
return sum; // Return the sum of 1's.
}
If you apply the above exampled dice roll to the command-line then the console window should display something like:
Sum of ones: 3
On a side:
When creating your dice[] Array from the command-line arguments (varArgs) you should validate the fact that valid values have been supplied before you add them into the Array. It may not be a big problem in this use-case because the application halts when an invalid value is detected but in the future, this may not always be the situation in another application you develop. Checking for non-numerical (integer) values would be a good idea as well. You application will crash if a letter was supplied in the command-line instead of a integer number. You cover the upper and lower inclusive numerical boundaries but nothing if there is a non-numerical value. This can be solved with a little change to your code:
int[] dice = new int[args.length];
for(int i = 0; i < args.length; i++) {
// If the command-line argument is anything other than 1 to 6...
if(!args[i].matches("[1-6]")) {
System.out.println("Error: Invalid value (" + dice[i]
+ ") in Command-Line arguments!");
return;
}
dice[i] = Integer.parseInt(args[i]);
}
You will notice that the String#matches() method is used for the condition of the if statement and passed to it is a small Regular Expression (regex) of "[1-6]". What this expression does is it will see if the value passed to the current (args[i]) argument it's checking is nothing more than a string representation of a integer numerical value consisting of a inclusive value from 1 to 6. Anything else and the validation fails. You will also note that the NOT operator (!) is used at the beginning of the condition. This would be the same as saying,
"If args[i] does not contain a string representation of a integer value
inclusively between 1 and 6 then, inform the User of an Invalid Argument
and shut down the application, otherwise, add it to the `dice[]` Array."

Find two numbers in array x,y where x<y, x repeats at least n/3 times and y at least n/4 times

I have been struggling to solve an array problem with linear time,
The problem is:
Assuming we are given an array A [1...n] write an algorithm that return true if:
There are two numbers in the array x,y that have the following:
x < y
x repeats more than n/3 times
y repeats more than n/4 times
I have tried to write the following java program to do so assuming we have a sorted array but I don't think it is the best implementation.
public static boolean solutionManma(){
int [] arr = {2,2,2,3,3,3};
int n = arr.length;
int xCount = 1;
int yCount = 1;
int maxXcount= xCount,maxYCount = yCount;
int currX = arr[0];
int currY = arr[n-1];
for(int i = 1; i < n-2;i++){
int right = arr[n-2-i+1];
int left = arr[i];
if(currX == left){
xCount++;
}
else{
maxXcount = Math.max(xCount,maxXcount);
xCount = 1;
currX = left;
}
if(currY == right){
yCount++;
}
else {
maxYCount = Math.max(yCount,maxYCount);
yCount = 1;
currY = right;
}
}
return (maxXcount > n/3 && maxYCount > n/4);
}
If anyone has an algorithm idea for this kind of issue (preferably O(n)) I would much appreciate it because I got stuck with this one.
The key part of this problem is to find in linear time and constant space the values which occur more than n/4 times. (Note: the text of your question says "more than" and the title says "at least". Those are not the same condition. This answer is based on the text of your question.)
There are at most three values which occur more than n/4 times, and a list of such values must also include any value which occurs more than n/3 times.
The algorithm we'll use returns a list of up to three values. It only guarantees that all values which satisfy the condition are in the list it returns. The list might include other values, and it does not provide any information about the precise frequencies.
So a second pass is necessary, which scans the vector a second time counting the occurrences of each of the three values returned. Once you have the three counts, it's simple to check whether the smallest value which occurs more than n/3 times (if any) is less than the largest value which occurs more than n/4 times.
To construct the list of candidates, we use a generalisation of the Boyer-Moore majority vote algorithm, which finds a value which occurs more than n/2 times. The generalisation, published in 1982 by J. Misra and D. Gries, uses k-1 counters, each possibly associated with a value, to identify values which might occur more than 1/k times. In this case, k is 4 and so we need three counters.
Initially, all of the counters are 0 and are not associated with any value. Then for each value in the array, we do the following:
If there is a counter associated with that value, we increment it.
If no counter is associated with that value but some counter is at 0, we associate that counter with the value and increment its count to 1.
Otherwise, we decrement every counter's count.
Once all the values have been processed, the values associated with counters with positive counts are the candidate values.
For a general implementation where k is not known in advance, it would be possible to use a hash-table or other key-value map to identify values with counts. But in this case, since it is known that k is a small constant, we can just use a simple vector of three value-count pairs, making this algorithm O(n) time and O(1) space.
I will suggest the following solution, using the following assumption:
In an array of length n there will be at most n different numbers
The key feature will be to count the frequency of occurance for each different input using a histogram with n bins, meaning O(n) space. The algorithm will be as follows:
create a histogram vector with n bins, initialized to zeros
for index ii in the length of the input array a
2.1. Increase the value: hist[a[ii]] +=1
set found_x and found_y to False
for the iith bin in the histogram, check:
4.1. if found_x == False
4.1.1. if hist[ii] > n/3, set found_x = True and set x = ii
4.2. else if found_y == False
4.2.1. if hist[ii] > n/4, set y = ii and return x, y
Explanation
In the first run over the array you document the occurance frequency of all the numbers. In the run over the histogram array, which also has a length of n, you check the occurrence. First you check if there is a number that occurred more than n/3 times and if there is, for the rest of the numbers (by default larger than x due to the documentation in the histogram) you check if there is another number which occurred more than n/4 times. if there is, you return the found x and y and if there isn't you simply return not found after covering all the bins in the histogram.
As far as time complexity, you goover the input array once and you go over the histogram with the same length once, therefore the time complexity is O(n) is requested.

Integer variable not following while loop conditions

I've been having an issue with my code concerning arrays and int variables. In the section that I have issues with, I'm trying to check if an array (in which the user inputs their own integers) is in an increasing order, and if it is in an increasing order, the array is printed; if not, an error message is displayed. I am trying to do this using int two variables, one called c1 and another called orderCheck1 (both initialized to 0).
int[ ] list1 = new int [10000];
int a1 =0;
int b1 =0;
int c1 =0;
int value1;
int orderCheck1 =0;
while (a1 ==0){
if (b1 < list1.length){
value1 = scan.nextInt();
//checks to see if value entered is positive
if (value1 >=0){
list1[b1] = value1;
b1++;
}
else{
a1 =1;
}
}
}
while (c1 <(list1.length-1)){
if (list1[c1] >list1[(c1+1)]){
orderCheck1 =1;
}
c1++;
}
if (orderCheck1 ==0){
for (int i =0; i < b1; i++){
System.out.print (list1[i] + " ");
}
}
else{
System.out.println ("ERROR: One or both arrays are not in an increasing order.);
}
Basically, if a number in the array is larger than the number following it, orderCheck will become 1. Later in the code, it checks if orderCheck1 is either zero or one. If orderCheck1 is zero, then the ints in the array are printed; if it is one, then the error message is displayed.
The issue is, no matter what I enter, orderCheck1 always becomes a one, so the error message is always printed. What is wrong with my code?
Note: When the user enters values into the array, they are supposed to enter a negative number to stop entering values.
The main problem, I believe, is that you've allocated a list of 10000 elements, and you don't use them all. Java initializes the elements to 0. (Note that in some other languages, a construct like this could initialize the elements to random garbage values.)
You then write a loop that inputs numbers until the user enters a negative number. This will set the first n elements of the loop for some number n. But the remaining elements do not get chopped off the array. They are still there, and they are still 0.
This causes a problem for this loop:
while (c1 <(list1.length-1)){
if (list1[c1] >list1[(c1+1)]){
orderCheck1 =1;
}
c1++;
}
Note that list1.length is still 10000, even though the user didn't enter 10000 values. Once an array is created with new int[10000] or something like that, that fixes the .length of the array. This length cannot be changed. That means c1 will go up to 9999, regardless of how many values were entered.
Therefore, at some point, you will hit a point where you start comparing to the 0 values that got put in the array when you created it. Since all the values the user entered are positive, that means list1[c1] > list1[c1+1] will be true when list[c1] is the last value entered, because list1[c1+1] will still be 0.
The solution is that instead of letting c1 go up to list1.length-1, you have to stop it when it gets to, I think, one less than the number of user entries. It looks like you already have a b1 that counts the number of entries, so the while needs to be changed to while (c1 <some-expression-that-uses-b1). I'll let you work on getting that upper limit right.
One more thing: When you have an array like this whose size isn't really known, it's better to use an ArrayList. Unlike an int[], an ArrayList<Integer> will grow as you add elements to it, and the size() method will return the actual number of elements added.
I would suggest a method:
static boolean isAscending(int[] nums) {
for (int i = 1; i < nums.length; i++)
if (nums[i - 1] > nums[i])
return false;
return true;
}
Note that this handles the edge case of arrays of size zero or one correctly.

I am having Problems with Arrays

I am having issues with this array code. It needs to have a number count that displays the numbers that are entered by the user. So for instance, if the user enters three four's it will say "4 3." I already have the majority of the code done, but it is just returning the first number that's entered.
import java.util.Scanner;
public class NumberCounts
{
public static void main(String args[])
{
int[] answer = new int [100];
inputArray(answer);
}
public static void inputArray(int[] Numbercounts)
{
System.out.println("This Program is written by Benjamin Barcomb\n");
Scanner kb = new Scanner(System.in);
System.out.print("How many numbers will you enter? : ");
kb.nextInt();
//int[] answer = new int[100];
int arryNum[] = new int[] {};
System.out.println("\nEnter numbers in [0, 100] range separated by a space:");
int input = kb.nextInt();
System.out.println("Number Count");
int[] counter = new int[] {input};
for (int i = 0; i < arryNum.length; i++) {
System.out.println(" " + (i + 1) + " " + counter[i]);
}
for (int i = 0; i < counter.length; i++) {
System.out.println(" " + (i + 1) + " " + counter[i]);
}
}
}
Where to start...
1) You create an array answer of length 100, pass it to your method, then never use it anywhere.
2) You ask the user to tell you how many numbers they are going to enter, you get that input with kb.nextInt(), then do nothing with it. You never assign that int to a variable.
3) You create an array arryNum and leave it empty. You never put anything into it, ever.
4) You ask the user to input numbers separated by spaces. You then take only the first int they enter.
Since it seems like you are just learning I will leave the coding to you. Hopefully if you can now see what certain parts of your code are doing you will be able to move on from there. My one tip would be to use more descriptive variable names. It makes it easier for you to read what is going on when you look at your code.
Some Solutions
1) Unless the requirements say you must pass an array into the inputArray() method, I would just remove it all together since you are doing all the other work in the method. I would remove int[] answer = new int [100]; call the method with no parameters inputArray() and change the signature of the method to just
public static void inputArray() { ... }
2) When you ask the user how many numbers they are going to enter you are basically asking them "How long should my array be?" When you get this int you should use it to make your new array. Something like
System.out.print("How many numbers will you enter? ");
int usersNumbers = new int[kb.nextInt()];
Notice I have changed the name of arrayNum to usersNumbers. It's more descriptive and makes reading your code easier.
3) Now you want to get all those numbers and put them into that array. Since you need to get multiple numbers you will need a loop. Again, unless the requirements say you have to, I would do this a bit differently. Instead of entering all the numbers on one line separated by spaces, I would ask for the numbers individually. Since we know the length of the array (how many numbers they are going to enter), we know how many times to prompt them.
System.out.println("\nEnter numbers in [0, 100] range.\n");
for (int i = 0; i < usersNums.length; i++) {
System.out.println("Enter Your Number:");
usersNums[i] = kb.nextInt();
}
4) Now onto counting the number of occurrences of each int entered. Since the user can enter their numbers in any random order it makes things tougher. Again, I'm not sure what exactly your requirements allow or not, but here is what I did. First I want to get a list of the unique numbers. For example, if the array is {2, 4, 2, 5, 2, 4} I want to get a list with {2, 4, 5}. Once I have that I can look at each of those numbers and go through the array counting how many times I see each one. An easy way to get a list of unique numbers is to put them into a Set. It is a data structure which doesn't allow duplicates. A TreeSet is a Set which puts the numbers in order, just to make it easier to read.
Set<Integer> uniqueNumbers = new TreeSet<Integer>();
for (int i : usersNums) { uniqueNumbers.add(i); }
Now that I have the list of unique numbers I can start counting. I start count at 0. Then for every number in the set, I look at every number in the array and see if they are the same. If they are, count goes up by 1. Once I get to the end of the array I print my results for that number, then reset count to 0.
int count = 0;
for (Integer i : uniqueNumbers) { //For every number in the Set
for (int j = 0; j < usersNums.length; j++) { //Look at every number in the array
if (i == usersNums[j]) { count++; } //If the same, count++
}
System.out.print(i + " - " + count + "\n"); //Print results
count = 0; //Reset Count
}
It seems you're only getting the first value because you only called nextInt() on your scanner once. You should ideally have a while loop to keep gathering user input. Also, I think you're trying to store your answers in an array, which really isn't ideal since you don't know how big your input will be. You should really use a list. Something along the lines of
List<Integer> data = new ArrayList<Integer>();
while (kb.hasNext()) {
data.add(kb.next());
}
Explain your code hope you understand how to fix it.
First, I assume you want your user to enter more than one number but you use nextInt which means
The java.util.Scanner.nextInt() method Scans the next token of
the input as an int.An invocation of this method of the form
nextInt() behaves in exactly the same way as the invocation
nextInt(radix), where radix is the default radix of this scanner.
Suggestion: try to use to while loop to read more number and quite when your user enter -999999 for example as a termination for your while loop.
Second, use Array is not right data structure to use because you do not know the size of array.
There are 2 ways to fix this issue:
1. first to ask the size of array from the user like how many numbers the user wants to input which is not what you want.
2. use another data structure that shrinks and expands by itself which is ArrayList
Third, you did not say whether you gonna have different numbers in your input like
1 1 2 3 3 4 4 5 or unsorted like `1 2 1 4 3 4 5`
or just your input includes the same numbers like
2 2 2 2 2 2 2
More info for third point is here

Counting Int Occurrences in an Array

I am trying to count the occurrences of integers in an array. I was able to get it to work by piecing together some code I found online but I don't really understand why its working. What I have is:
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[hand.length];
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
for (int i = 1; i < numOccurence.length; i++)
if (numOccurence[i] > 0)
System.out.println("The number " + i + " occurs " + numOccurence[i] + " times.");
The output is:
The number 2 occurs 2 times.
The number 3 occurs 1 times.
The number 4 occurs 2 times.
How is this code counting the number of occurrences properly? I don't see how its accomplishing this. Thank you in advance!
This is only working because you've a good luck. Try making the second element in the hand array as 5 and see what happens. Its because the number present at the current index of hand is taken as the index of array numOccurence. In case of a number greater than or equal to the length of the numOccurence, you'll get the ArrayIndexOutOfBoundsException.
Thereforce, you can better use a Map for this where the key would be the number and the value could be its count.
Something like this:-
Map<Integer, Integer> numOccurence = new HashMap<Integer, Integer>();
for (int i = 0; i < hand.length; i++) {
int cnt = 1;
if (numOccurence.containsKey(hand[i])) {
cnt = numOccurence.get(hand[i]);
cnt++;
}
numOccurence.put(hand[i], cnt);
}
This code does not really work. At least it does for the author's use case but probably not for yours.
Try with {2, 4, 99, 2, 4}; as hand and it will fail.
The author takes the number found in hand as the index of array numOccurence.
numOccurence has the following structure : {nb occ of 0; nb occs of 1;...; nb occs of 4}. Here 99 will be out of bounds.
When you create an array
int[] numOccurence = new int[hand.length];
it is populated by their default values. For primitive int this value is 0.
This will of course only work if hand contains numbers less than or equal to max index (length -1) of the array otherwise it's ArrayIndexOutOfBound for you mister!
Actually it's the same method for creating histogram for picture ;)
You create a table where you will gather the occurrence.
numOccurence[0] will stock the number of 0
numOccurence[1] will stock the number of 1
etc.
That's what is done by this
for (int i = 0; i < hand.length; i++)
numOccurence[hand[i]]++;
it adds 1 to the value in the case corresponding to the number hand[i]
so if you look at this step by step
first he will take hand[0] = 2
so he will put
numOccurence[2] = numOccurence[2] + 1 ;
which is same (but faster to write) as
numOccurence[2]++;
This kind of performing a count is called counting sort.
The advantage of counting sort is it's speed. The disadvantage is the memory requirements when sorting big numbers.
There is a bug in the code:
int[] numOccurence = new int[hand.length];
numOccurence needs to be as long as the highest number in the list (not the number of numbers in the list). Try changing one of the numbers to 15 and you will get an exception.
The code iterates through the given array hand. it takes each value encountered as an index into the array numOccurrence. for each number n in hand, this will happen exactly as often as n occurs in hand, and each time this happens, the nth element of numOccurrence will be incremented.
thus numOccurrence is effectively an array of counters (assuming that the array elements are initialized with 0).
drawbacks of this approach:
the number of counters allocated depends on the magnitude of numbers in your handarray.
if the numbers in your hand array are distributed sparsely, most of the allocated space is never used.
alternative
you could improve the code by sorting hands first. in the sorted array the indexes of all occurrences of a given number are contiguous, so you scan the sorted array once needing a single counter only to compile the frequencies.
First of all the code is wrong. You should set the size of numOccurence array to the max number value from hand array + 1. For example:
int[] hand = {2, 100};
int[] numOccurence[] = new int[101];
(you should obviously find max number programatically)
Now let's take a look at the algorithm.
It takes each number from hand array, treats it as a numOccurence index value and increments number at that index by 1 in hand array. Note that all elements of numOccurence array are 0 by default at the beginning.
int[] hand = {2, 4, 3, 2, 4};
int[] numOccurence = new int[5];
Steps:
i = 0 (nothing happens, because there is no 0 in hand array)
i = 1 (same situation as for 0)
i = 2 (there are two 2 numbers in hand array, so we do operation numOccurence[2] += 1 twice, which in result gives 0 + 1 + 1 = 2. So we got numOccurence[2] = 2)
it continues for all numbers from 0 to max number from hand array (here: 100).

Categories