I have an array that I populate with 6 randomly generated numbers. First it generates a random number between 1 and 49 and then checks it against the numbers in the array. If it finds a duplicate it should generate a random number again and then perform the check once again. If there are no duplicates then the number is added to the array.
Here's the code:
public void populateArray()
{
for(int i = 0; i < numberLine.length; i++)
{
randomNumber = 1 + randomGen.nextInt(49);
for(int j = 0; j < i; j++)
{
if (numberLine[j] == randomNumber)
{
i--;
}
else
{
continue;
}
}
if(i >= 0)
{
numberLine[i] = randomNumber;
}
else
{
continue;
}
}
Arrays.sort(numberLine);
}
However, for some reason this still lets in a duplicate, though rarely (about 1 in 50 arrays), such as 6 6 16 24 34 46
. But when I try to duplicate this by taking out the random number element and using a number like 30, I am unable to reproduce the result. What's going wrong?
Here is what can happen. Let's say you've already drawn
1
and2
. On the third iteration you draw1
again. What happens is that your inner loop would decrementi
once, after whichnumberLine[i] = randomNumber
will place the1
into the second position. You now have1, 1
in your array. QED.Having figured out the bug, I have a couple of suggestions:
1) The following:
should be
Otherwise you're looking at positions that are yet to be populated.
2) I'd rewrite the whole algorithm using a
SortedSet
: simply keep adding random numbers to the set until it has the desired size. At the end, usetoArray()
. This will automatically take care of the de-duplcation and the sorting, and will have a better time complexity than your current solution.All the other suggestions are equally good, here is some code which I think should work:
It would be a lot easier with collections, for example a
TreeSet
which is both sorted and without duplicateUse
toArray()
after that if you really want to have an array.Actually since your domain is limited to integers between 1 and 49 it's better to use an array of booleans to indicate whether the number was already drawn:
edit
That still has potential infinite loop.
You're drawing 6 numbers out of 49 without duplicates. The correct solution would be:
Finite loops, the same probability distribution as the original one. Instead of retrying the draw when a duplicate is encountered you just eliminate the possibility of drawing the duplicate beforehand. It's basically emulating the real lotto-like draw.