I need to fill an array A with 5 random numbers from a possible 50. Duplicates are allowed. I then need to fill the same array a second time but with unique numbers that did not appear in the first or second filling of the array. I am using the code below to generate the array the second time. I am stuck on how to search the first array for duplicates at the same time. Any help appreciated! Thanks
boolean drawn;
for (int i=0; i<A.length; i++) {
do {
drawn = false;
A[i] = 1 + (int)(Math.random() * 50);
for (int j=0; j<i; j++)
if (A[i] == A[j])
drawn = true;
} while (drawn);
5 Answers 5
Use a List<> to keep track of all allowed numbers, and as you use them, remove them from the list. Then, for your 'second pass', instead of always getting a random number * 50, get a random number * list size(). Then the actual number you use is list.get(location) instead of just number.
(your list will start out as 1,2,3,4,5, but then when 3 is used, the list will become 1,2,4,5, ..., So that when you get the next "random()" number of 3, that is actually a 4.)
Comments
I would do this:
List<Integer> choices = new ArrayList<Integer>();
Random r = new Random();
for(int i = 0; i <N;i++)
{
choices.add(r.nextInt(N-1)+1;
}
Set<Integer> uniques = new HashSet<Integer>();
Collections.shuffle(uniques);
//remove first 5 entries from uniques
//repeat for second pass
This of course has the possibility (as minimal as it is) that there will be a set remaining of less than size 5.
Comments
You could create a list containing your 50 numbers, and use a Random to get 5 indices between 0 and 50, to create your first random array.
For the second pass, create a copy of the first list, but remove the numbers that are in the first random array. Then shuffle this second list (using Collections.shuffle()), and take the 5 first elements.
Comments
You have to use one extra array each time you want to fill the array as you need to store the previous array elements. Something like:
boolean drawn;
System.arraycopy( A, 0, B, 0, A.length );
for (int i=0; i<A.length; i++) {
do {
drawn = false;
A[i] = 1 + (int)(Math.random() * 50);
for (int j=0; j<A.length; j++)
if (A[i] == B[j])
drawn = true;
for (int j=0; j<i; j++)
if (A[i] == A[j])
drawn = true;
} while (drawn);
`
1 Comment
Store your 50 random number candidates in an array random of size 50
Keep a counter initially set to random.length.So, herecounter will be initialized to 49.
Then Generate a number r from 0 to counter-1 and choose random[r] as your number.
Now go ahead and swap random[r] with random[counter-1]. Decrement counter so that next time you will only be searching the first 49 elements of the array, and continue this process whenever you pick a number.
Now simply If you want a number that you have not chosen before, generate r from 0 to counter-1 so that random[r] comes from the unique elements in the array which will be in the beginning.
int[] randoms= new int[50];
.
. //populate your array with the candidate numbers
.
int counter= randoms.length;
Random rand = new Random();
public int getUnique(){
//Get a random number in the range 0 to counter-1
int r = rand.nextInt(counter);
int myElement = randoms[r];
randoms[r] = randoms[counter-1];
randoms[counter-1]= myElement;
counter--;
return myElement;
}
And whenever you want to allow duplicates, generate an r from 0 to random.length -1 and choose random[r] as your number. Notice that we still have to keep track of the numbers used so that getUnique() still works:
public int getAny(){
//Get a random number in the range 0 to random.length-1
int r = rand.nextInt(random.length);
int myElement = randoms[r];
if(r < counter){
randoms[r] = randoms[counter-1];
randoms[counter-1]= myElement;
counter--;
}
return myElement;
}
Listinstead of an array, you could leverage the contains() method.