Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing a number from a Java RNG's range?

I'm currently using Java's RNG Random r = new Random(), and having it generate a new integer between 0 and 5 in a while loop.

while (someBoolean == false) {
        int i = r.nextInt(6);
           ....
 }

What I would like to do, is to remove a number from the range (for instance, 4) so that the RNG still generates a new number between 0 and 5, excluding one of the values.

My current best bet is the following:

 while (someBoolean == false) {
        int i = r.nextInt(6);
           if (i == removedInt) { continue; }
          ....
 }

However I'm worried this could cause long runs in my code where the RNG is constantly returning a number that I don't want.

[For clarity; the number that is being returned is a column in a Connect4 grid, or 2D int array. The method is randomly placing moves in columns until a column fills up, at which point I no longer want to be able to play in that column. ]

Any help appreciated :)

like image 708
JonnyH Avatar asked Feb 12 '15 15:02

JonnyH


People also ask

How do you control the range of Math random in Java?

random() is used to return a pseudorandom double type number greater than or equal to 0.0 and less than 1.0. The default random number always generated between 0 and 1. If you want to specific range of values, you have to multiply the returned value with the magnitude of the range.

How do you generate a random number between 1000 and 9999 in Java?

How do you generate a random number between 1000 and 9999 in Java? int randomNumber = ( int )( Math. random() * 9999 ); if( randomNumber <= 1000 ) { randomNumber = randomNumber + 1000; Math. random() is a method that generates a random number through a formula.

How do you generate a random number between 1 and 3 in Java?

Random rand = new Random(); int x = rand. nextInt(10); x will be between 0-9 inclusive.


2 Answers

ArrayList<Integer> myInts = new ArrayList<Integer>();
myInts.add(1);
myInts.add(2);
myInts.add(3);
myInts.add(4);
int i = myInts.get(r.nextInt(myInts.size())); // 1,2,3,4
myInts.remove(3);
int j = myInts.get(r.nextInt(myInts.size())); // 1,2,4

The code selects random entry from allowed list of integers.

PS Please note, that if you have a big range of numbers, then creating an ArrayList of thousands upon thousands of integers might not be the best idea.

like image 189
Gerino Avatar answered Oct 09 '22 00:10

Gerino


Although you could use a List enumerating the numbers you want to generate and exclude/remove the one you want to exclude, this is only efficient for small ranges. If you want to generate a random number in a large range, this solution becomes quite inefficient and unfeasable.

Solution using only 1 Random.nextInt() call

If you want to generate random numbers in the range of 0..5 both inclusive, you can do that with r.nextInt(6).

If you want to exlude a number, e.g. 4, that means the range is smaller by 1, so use r.nextInt(5) and if the result is the excluded number, then return the max allowed which is 5 (because it will never be generated because you used max - 1).

It looks like this:

// Returns a random number in the range 0..5 (0 and 5 included), 4 excluded
public int nextRand() {
    int i = r.nextInt(5);
    return i == 4 ? 5 : i;
}

General solution

Here is a general solution which takes the min, max and the excludable numbers as parameters:

/**
 * Returns a random number in the range min..max both included, but never the excluded.
 */
public int nextRand(int min, int max, int excluded) {
    if (max <= min || excluded < min || excluded > max)
        throw new IllegalArgumentException(
                "Must be: min <= excluded <= max AND min < max");

    int i = min + r.nextInt(max - min);  // r is a java.util.Random instance
    return i == excluded ? max : i;
}

So for example if you call nextRand(0, 5, 3), it will only return a random number being one of 0, 1, 2, 4, 5.

like image 45
icza Avatar answered Oct 09 '22 01:10

icza