This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 4 years ago.
So, I'm working on a problem that has me adding two die rolls 'X' amount of times, then recording the frequency in an array, here is what I have
int [] counters = new int [11];
for (int i = 0; i <1001; i++){
//have to add +1 so I don't get 0
++counters[((die1.nextInt(6)+1)+(die2.nextInt(6)+1))];
}
System.out.print(counters);
And I'm getting this error:
java.lang.ArrayIndexOutOfBoundsException: 12
//have to add +1 so I don't get 0
No you really don't.
In Java arrays are 0-based. Meaning an array of 11 elements has indices 0 .. 10.
Random.nextInt(n) returns a value between 0 and n-1.
Therefore the expression ((die1.nextInt(6)+1)+(die2.nextInt(6)+1)) will be between 2..12.
Either increase the size of the array to 13 so that 12 fits (the first 2 elements will remain unused), or simply remove +1's:
Random die1 = new Random(), die2 = new Random();
int [] counters = new int [11];
for (int i = 0; i <1001; i++){
++counters[die1.nextInt(6)+die2.nextInt(6)];
}
Also you can't print an array with print(). A possible solution is to print each element individually:
for (int i = 0; i < counters.length; ++i) {
System.out.print((i+1) + ":" + counters[i] + " ");
}
System.out.println();
You have two dice, and the result of a die roll can be from 0 to 5. I assume the 1001 means you want to roll the two dice 1001 times. Please let me know if I missed anything here.
In this case your min roll would be a 0, and max 10. But, adding 1 to both dice rolls before accessing would mean your index goes from 2 to 12 which causes your ArrayIndexOutOfBoundsException.
Just don't add anything to the roll. Remember java arrays start from 0, so a range of 0 to 10 is fine.
Quick example:
public static class Die {
static Random rand = new Random();
public static int nextInt(int val) {
return rand.nextInt(val);
}
}
public static void main(String[] args) {
int[] counters = new int [11];
for (int i = 0; i <1001; i++){
//no need to add anything
++counters[Die.nextInt(6) + Die.nextInt(6)];
}
System.out.print(Arrays.toString(counters));
}
Example output:
[27, 60, 81, 106, 157, 175, 120, 109, 81, 55, 30]
Which we can translate to mean that a "2" was rolled 27 times, "3" 60 times, etc.
Related
This question already has answers here:
How do I generate random integers within a specific range in Java?
(72 answers)
Closed 3 years ago.
I am having trouble placing the random generator in the array, how can I get #20 random numbers from 0-9 in the array? Then you count the occurrences of those numbers.
import java.util.Random;
public class CountDigits {
public static void main(String[] args) {
Random digit = new Random();
int Random[] = new int [20];
int Digits[] = {0,1,2,3,4,5,6,7,8,9};
int Count [] = new int [10];
for ( int i = 0; i < Digits.length; i++) {
for( int j = 0; j < Random.length; j++) {
if ( Digits [i] == Random [j] )
Count[i]++;
}
}
for ( int i = 0; i < Count.length; i++) {
if ( Count[i] == 1)
System.out.printf(" %d occurs 1 time " , Digits[i] );
else
System.out.printf("%d occurs %d times" , Digits[i], Count[i]);
}
result so far::
0 occurs 20 times1 occurs 0 times2 occurs 0 times3 occurs 0 times4 occurs 0 times5 occurs 0 times6 occurs 0 times7 occurs 0 times8 occurs 0 times9 occurs 0 times
You need to actually get a Random number, and get within the range. The Java Random will provide the necessary capability, and includes a .nextInt(int bound) that returns between 0 and bound:
public int nextInt(int bound)
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence.
So something like:
Random rnd = new Random();
int num = rnd.nextInt(10); // returns between 0 and 9
Given that, you have two other questions:
- Generating 20 numbers
- Counting
Knowing that the number of possible entries is between 0 and 9, it is easy to use an array to hold the counts.
int[] counts = new int[10]; // holds between 0 and 9
for (int i = 0; i < 20; ++i) {
int num = rnd.nextInt(10);
counts[num]++;
}
The output of the counts array will give the count of the number of times a given number between 0 and 9 was randomly generated.
See an example here
You forgot to assign random numbers to the array elements.this answer to see how random numbers are generated.
You need to call Random object's nextInt(an integer) method. If you give 25 to it, it will return a random integer between 0-24 inclusive.
Example Usage:
Random rand = new Random();
int random_int = rand.nextInt(50); // --------> Random integer 0-49
And the full code:
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random digit = new Random();
int Random[] = new int[20];
for (int x=0;x<20;x++) {
Random[x] = digit.nextInt(10);
}
int Digits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int Count[] = new int[10];
for (int i = 0; i < Digits.length; i++) {
for (int j = 0; j < Random.length; j++) {
if (Digits[i] == Random[j])
Count[i]++;
}
}
for (int i = 0; i < Count.length; i++) {
if (Count[i] == 1)
System.out.printf(" %d occurs 1 time ", Digits[i]);
else
System.out.printf("%d occurs %d times", Digits[i], Count[i]);
}
}
}
Outputs :
0 occurs 2 times1 occurs 2 times 2 occurs 1 time 3 occurs 3 times4 occurs 6 times 5 occurs 1 time 6 occurs 2 times7 occurs 0 times 8 occurs 1 time 9 occurs 2 times
You can print the random numbers like this
for (int x=0;x<20;x++) {
System.out.println(Random[x]);
}
You can try this:
Create an array of int with length 20, then use a simple for loop where you are gonna generate a random number and them put it inside the array
int[] random = new int[20];
for(int i=0;i<20;i++){
int r = Math.floor(Math.random()*9+1);
random[i]=r;
}
Am in the middle of an encryption algorithm, I have written the code to randomly shuffle a series of numbers in java.
Here is the code:
public class permute6 {
public static void main(String args[])
{
Random rand = new Random();
int arr[] = {10,20,30,40,50,60,70,80};// Original Array
System.out.println("Original array is" );
for(int k = 0; k<arr.length;k++ )
System.out.print(arr[k] + "\t" );
System.out.println(" ");
int max = arr.length - 1;
int min = 0;
int rnum;
int larr = arr.length - 1;
int[] parr = new int[arr.length];// to store the permuted array
int flag = 0;// 'flag' to flag the recurring number
int plen = parr.length - 1;
for(int i = 0 ; i < arr.length ; i++)
{
rnum = (rand.nextInt((max-min)+1) + min);// roll for the
random number
parr[plen] = arr[rnum];
arr[rnum] = arr[larr];
larr--;// to reduce the size of the original array
plen--;// to make the parr to act like a stack
max--;
}
System.out.println("Permuted array is" );
for(int k = 0; k<arr.length;k++ )
System.out.print(parr[k] + "\t" );
System.out.println();
}
}
If the initial array is {10,20,30,40,50,60,70,80}
then one of the shuffled result is
50 20 30 10 60 80 70 40
Now if I transmit this array, then how to get back the original sequence at the destination side? What can be done to keep track of the sequence?
What is missing here....Any help is appreciated!!
You can submit two arrays to destination parr and temp;
parr: [50 20 30 10 60 80 70 40]
and
temp(It is basically difference of permuted array from original e.g. parr-arr):
like {50, 20, 30, 10, 60, 80, 70, 40} - {10,20,30,40,50,60,70,80}
temp = {40,0,0,-30,10,20,0,-40}
Now,
At destination again get difference of parr and temp "parr-temp"
{50, 20, 30, 10, 60, 80, 70, 40} - {40,0,0,-30,10,20,0,-40}
= {10,20,30,10-(-30),50,60,70,40-(-40)}
You will get your original sequence without sending original array at destination
Another solution came into mind related to previous one but it will avoid transferring two arrays to destination. Merge both temp and parr into a single array say newArr = {50,40,20,0,30,0,10,-30,60,10,80,20,70,0,40,-40}
and at destination just subtract each element from the next element and you will get your original array using only one array.
I am currently trying to set up a sorting algorithm for an array that scans for the highest and lowest number and places them into a new array, two at a time. I've noticed that it appears to work only in certain conditions. For example, I can input it as {5, 3, 10, 7} or {3, 5, 10, 7}, but {7, 3, 5, 10} produces an IndexOutOfBoundsException: index 1, size: 1;
Here's the code:
import java.util.Scanner; // program uses class Scanner
import java.util.ArrayList; //helps with arrays
public class ArrayAlg
{
// main method begins execution of Java application
public static void main( String[] args )
{
// create a Scanner to obtain input from the command window
Scanner input = new Scanner( System.in );
boolean AS = false; //array sorted.
int hi = 0; //high number
int low = 100; //set to 100 for logic reasons.
int oldhi = 0;
int oldlow = 0;
int NI = 0;
int addA = 0;
int p = 0; //places, moves right after one scan to place the next int
int n = 1; //number of times, moves left after one to place the next int
String cont = "n";
ArrayList<Integer> IParray = new ArrayList<Integer>(); //input array
ArrayList<Integer> Sarray = new ArrayList<Integer>(); //sorted array
while (cont.equals("n"))
{
System.out.print("Please enter a number for the array: ");
addA = input.nextInt();
IParray.add(addA);
NI++;
System.out.print("\n is that all? (y/n): ");
cont = input.next();
}
for (int c = 0; c < NI; c++) //adds 0 so sorting will be easier
Sarray.add(0); //matches the inputted array
System.out.print("The inputted array: ");
System.out.print(IParray);
System.out.println("");
while (AS == false){
hi = 0;
low = 100;
for (int i = 0; i < IParray.size(); i++)
{
if (IParray.get(i) < low)
low = IParray.get(i);
if (IParray.get(i) > hi)
{
//if (IParray.get(i) > hi) currently commented out, doesn't effect the logic by the looks of it.
hi = IParray.get(i);
}
}//end for
Sarray.set(p, low); //sets the number in the left most position then moves to the right
Sarray.set(Sarray.size() - n, hi); //sets the number to the rightmost position and moves left
p++; //increase place count to the right
n++; //increases the place count to the left
oldhi = IParray.indexOf(hi); //oldhi becomes the index of the recent highest number.
oldlow = IParray.indexOf(low); //oldlow becomes the index of the recent lowest number
IParray.remove(oldhi); //removes the highest number at the index
IParray.remove(oldlow); //removes the lowest number at the index, exceptions occurs right here.
System.out.print("The inputted array: ");//mostly here to see what the inputted array looks like after one iteration
System.out.print(IParray);
System.out.println("");
System.out.print("The sorted array: ");
System.out.print(Sarray);
System.out.println("");
if (IParray.isEmpty() == true) //checks to see if the input array is empty
AS = true;
else
AS = false;
}//end while
} // end method main
} // end class ArrayAlg
Can anyone give me any hints on why this might be occurring? I've been trying this out for the past hour or so. Tried Googling and searching this site for answers but no luck
You are getting the index out of bounds because it is trying to remove an index that does not exist. When it is removing indexes it removes lowest first causing the whole array index to shift downwards. It does not keep it's original index.
[0] = 7
[1] = 3
[2] = 5
[3] = 10
When removing the high number, 10, it becomes:
[0] = 7
[1] = 3
[2] = 5
When removing the low number it becomes:
[0] = 7
[1] = 5
The next loop you remove 7 first leaving only 5 at index 0 but your code is calling to remove index 1 giving you an out of bounds exception.
To fix this, let it dynamically get the index when the remove method is called.
IParray.remove(IParray.indexOf(hi)); //removes the highest number at the index
IParray.remove(IParray.indexOf(low)); //removes the lowest number at the index
You should have been able to quickly find this error by running your code in debugging mode and then stepping through the code that is throwing the exception (Line 73).
You might not be able to find a higher value and lower value comparison to previous ones. For example, input array was {7, 3, 5, 10}, now hi is 10 and low is 7, they were removed from IParray.
for (int i = 0; i < IParray.size(); i++)
{
if (IParray.get(i) < low)
low = IParray.get(i); // low becomes 3
if (IParray.get(i) > hi) //!!! never able to find a higher value than 10 !!!
{
//if (IParray.get(i) > hi) currently commented out, doesn't effect the logic by the looks of it.
hi = IParray.get(i);
}
}
In that case, low and high points to previous values, which was removed from the array since last iteration, so oldhi and oldlow would be -1, and you got the exception for IParray.remove(-1)
oldhi = IParray.indexOf(hi); // 10 is not in the array anymore, you got -1
oldlow = IParray.indexOf(low);
IParray.remove(oldhi); // you got exception here as you remove(-1)
IParray.remove(oldlow);
im trying to make an array of 10 different elements with Random(), so basically i have this
public static int[] RandomArray (int xArra[]) throws java.io.IOException {
Random Rand = new Random();
int nal;
for (int i = 0; i < xArra.length; i++) {
nal = Rand.nextInt(11); /*I would like to make this thing work with any
numbers, for example, changing this to 50 or 100.
In an array of 10 elements it should be
impossible to have a duplicate because with
11 it just prints from 1 to 10.
Thats why i put 11 here. */
for ( int j = 0; j < xArra.length; j++) {
if (nal == xArra[j]) {
nal = Rand.nextInt(11);
j=0;
}
}
xArra[i] = nal;
}
return xArra;
}
Basically im storing a random number in nal and I run my array in a second For to check
this random number with the already given ones, and if its equal to any number given in the array it changes it with random again, and runs the For again checking that the new number isnt duplicated, if its not, I stored in xArra[i].
When i run it 3 times, the results look like this:
First run:
8
1
6
4
3
2
10
8
9
7
Second run:
9
3
8
10
7
1
4
5
9
6
Third run:
3
5
2
3
6
7
1
4
10
9
So, as you can see i almost though i had it but it duplicates just 1 number, no 2 or 3, so basically i just want to make this thing work. I just want to print 10 random numbers with no duplicate, no repeats.
Heres my full code:
import java.io.*;
import java.util.*;
public class ArraynoR {
public static void main (String[] args) throws java.io.IOException {
int Array[]= new int [10];
RandomArray(Array);
for(int i=0; i<Array.length; i++){
System.out.println("Array[" + (i + 1) + "]:" + Array[i]);
}
}
public static int[] RandomArray (int xArra[]) throws java.io.IOException... //up
}
Please forgive my bad english, I hope I explained myself.
Thanks!
Instead of storing and searching for duplicates, create an ArrayList containing the numbers in the range of interest. Use Collections.shuffle() to randomize the values, then select however many you want from the shuffled set. Guaranteed to give no duplicates, and much more efficient than a search/reject approach.
ADDENDUM
Perhaps not the prettiest code, but it works and gives the idea...
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class ShuffleDemo {
public static int[] RandomArray(int len) {
ArrayList<Integer> al = new ArrayList<Integer>(len);
for(int i = 1; i <= len; ++i) { // initialize the ArrayList with values 1 to len
al.add(i);
}
Collections.shuffle(al); // shuffle to random order
int[] results = new int[len];
// switching return type to ArrayList could eliminate the following loop
for(int i = 0; i < len; ++i) { // copy to array of ints
results[i] = al.get(i); // note: create a subset by reducing
} // the upper bound for this loop
return results;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(RandomArray(10)));
}
}
Set j=-1 when you are resetting for the inner for loop and try it. Then it should work
for ( int j = 0; j < xArra.length; j++) {
if (nal == xArra[j]) {
nal = Rand.nextInt(11);
j=-1;
}
}
At the end of the for loop the loop increments the variable so when you set it to 0, before the next check it becomes 1 due to the internal code of the for loop
you can use the method nextPermutation of the class org.apache.commons.math3.random.RandomDataGenerator (see help here docs) in Apache Math. This method generate random numbers without repetition.
I have a method that is not working properly.
The method is supposed to sort a set of numbers from 1 to 20 randomly (each number
must appear just once).
My issue here is that when I run the program, some numbers are repeated several times.
The code is the following:
public static int randomize(int index) {
//This array will hold the 20 numbers.
int[] randomIndex = new int[20];
Random ranNum = new Random();
for (int x = 0; x<20; x++) {
int temp;
//The number is generated randomly and saved in temp.
temp = ranNum.nextInt(20);
//This loop skips the first index.
if (x != 0){
/*Here, the loop is supposed to compare a generated number with
the previous one*/
for (int y = 1; y<=x; y++) {
while(temp == randomIndex[x-y] ) {
/*If the while loop finds that temp variable matches any previous
number it will generate another random number for it until it finds
no matches.*/
temp = ranNum.nextInt(20);
}
}
}
/*Once no match has been found for temp, the number is assigned to an index,
and the loop is executed with a x variable increment.
randomIndex[x] = temp;
}
//Finally the array with the set of random numbers is sent to the main function.
return randomIndex[index];
}
And I got the following output:
19, 19, 5, 16, 6, 2, 18, 1, 15, 1, 5, 19, 11, 4, 18, 0, 5, 18, 10.
So now I have no idea what to do. :C
When you use Random.nextInt(), there's no guarantee that the numbers generated are unique.
You should generate numbers from 1 to 20 first, then shuffle the numbers. Now the question is changed to "How to shuffle the numbers randomly?"
Perhaps you can refer the implementation of JDK Collections.shuffle().
The algorithm for shuffling the numbers are simple:
Pick first element in the array and swap it with a number at random position.
Repeat step 1 until the last element.
You can avoid it by using something like this:
final Random random = new Random();
final HashSet<Integer> integers = new HashSet<>();
while(integers.size() < 20) {
integers.add(random.nextInt(20));
}
System.out.println(integers);
It looks like you're trying to generate your random numbers by rejection -- that is, by comparing each random number with all previously accepted numbers, and re-generating new ones until you find one that is is different from all of them.
As others have mentioned, it would be far more efficient to generate the numbers from 1 to 20, and shuffle them with a random permutation. However, if implemented correctly, your approach should work... eventually.
A random shuffle implementation might look something like this:
for(int i=0; i<20; i++) { // index goes from 0..19
randomIndex[i] = i + 1; // value goes from 1..20
}
for(int i=0; i<20; i++) {
int j = i + ranNum.nextInt(20 - i); // choose random j from i <= j < 20
int temp = randomIndex[i]; // swap elements i and j
randomIndex[i] = randimIndex[j];
randomIndex[j] = temp;
}
The are two reasons why your posted code generates duplicates. First, when you reject a candidate random number and re-generate a new one, you need to compare it against all existing numbers, restarting you inner (y) loop from the beginning. Your existing code doesn't do that.
Second, I believe that the new Random() constructor generates a different seed each time it is called. If so, your randomize() function is generating a completely different random list each time, and returning the selected index from it. In any case, it makes more sense to return the entire array, instead.
I edited your function for generate array from 1 to 20:
public static int[] randomize() {
int[] randomIndex = new int[20];
Random ranNum = new Random();
boolean isAlreadyIn;
boolean isZero;
int x = 0;
while (x < 20) {
isAlreadyIn = false;
isZero = false;
int temp;
temp = ranNum.nextInt(21);
for(int i = 0; i < randomIndex.length; i++){
if(temp == 0)
isZero = true;
if(temp == randomIndex[i])
isAlreadyIn = true;
}
if (!isZero && !isAlreadyIn){
randomIndex[x] = temp;
x++;
}
}
return randomIndex;
}
hope it will be helpful.