Woong-Sup Jung - 6 months ago 39

Java Question

In this case, the MAX is only 5, so I could check the duplicates one by one, but how could I do this in a simpler way? For example, what if the MAX has a value of 20?

Thanks.

`int MAX = 5;`

for (i = 1 , i <= MAX; i++)

{

drawNum[1] = (int)(Math.random()*MAX)+1;

while (drawNum[2] == drawNum[1])

{

drawNum[2] = (int)(Math.random()*MAX)+1;

}

while ((drawNum[3] == drawNum[1]) || (drawNum[3] == drawNum[2]) )

{

drawNum[3] = (int)(Math.random()*MAX)+1;

}

while ((drawNum[4] == drawNum[1]) || (drawNum[4] == drawNum[2]) || (drawNum[4] == drawNum[3]) )

{

drawNum[4] = (int)(Math.random()*MAX)+1;

}

while ((drawNum[5] == drawNum[1]) ||

(drawNum[5] == drawNum[2]) ||

(drawNum[5] == drawNum[3]) ||

(drawNum[5] == drawNum[4]) )

{

drawNum[5] = (int)(Math.random()*MAX)+1;

}

}

Answer

The simplest way would be to create a list of the possible numbers (1..20 or whatever) and then shuffle them with `Collections.shuffle`

. Then just take however many elements you want. This is great if your range is equal to the number of elements you need in the end (e.g. for shuffling a deck of cards).

That doesn't work so well if you want (say) 10 random elements in the range 1..10,000 - you'd end up doing a lot of work unnecessarily. At that point, it's probably better to keep a set of values you've generated so far, and just keep generating numbers in a loop until the next one isn't already present:

```
Random rng = new Random(); // Ideally just create one instance globally
// Note: use LinkedHashSet to maintain insertion order
Set<Integer> generated = new LinkedHashSet<Integer>();
while (generated.size() < numbersNeeded)
{
Integer next = rng.nextInt(max) + 1;
// As we're adding to a set, this will automatically do a containment check
generated.add(next);
}
```

Be careful with the set choice though - I've very deliberately used `LinkedHashSet`

as it maintains insertion order, which we care about here.

Yet another option is to *always* make progress, by reducing the range each time and compensating for existing values. So for example, suppose you wanted 3 values in the range 0..9. On the first iteration you'd generate any number in the range 0..9 - let's say you generate a 4.

On the second iteration you'd then generate a number in the range 0..8. If the generated number is less than 4, you'd keep it as is... otherwise you add one to it. That gets you a result range of 0..9 without 4. Suppose we get 7 that way.

On the third iteration you'd generate a number in the range 0..7. If the generated number is less than 4, you'd keep it as is. If it's 4 or 5, you'd add one. If it's 6 or 7, you'd add two. That way the result range is 0..9 without 4 or 6.