Java Generating Non-Repeating Random Numbers

Java generating non-repeating random numbers

Integer[] arr = {...};
Collections.shuffle(Arrays.asList(arr));

For example:

public static void main(String[] args) {
Integer[] arr = new Integer[1000];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
Collections.shuffle(Arrays.asList(arr));
System.out.println(Arrays.toString(arr));

}

Printing Non Repeating Random Numbers within a range

Currently, your set does nothing to prevent duplicates. You should have declared your set as a field, instead of a local variable. The set essentially keeps track of which numbers have been generated.

public class RandomNumberGenerator {

private int minimum;
private int maximum;
private Random random = new Random();
private Set<Integer> hSet = new HashSet<>();

public RandomNumberGenerator(int min, int max)
{
minimum = min;
maximum = max;
}

public void printRandomNumber()
{
int range = maximum - minimum + 1;
int randomValue = 0;

do
{
randomValue = minimum + random.nextInt(maximum - minimum + 1);
} while(!hSet.add(randomValue));

System.out.println("The next random number is: " + randomValue);
}
}

You should also add a method call shouldReset to indicate whether all the numbers are generated:

public boolean shouldReset() {
return hSet.size() >= maximum - minimum + 1;
}

and a reset method:

public void reset() {
hSet.clear();
}

Another way to do this is to shuffle a list of all the available numbers, and return the elements of the shuffled list sequentially:

public class RandomNumberGenerator {

private int minimum;
private int maximum;
private Iterator<Integer> iter;

public RandomNumberGenerator(int min, int max) {
minimum = min;
maximum = max;
reset();
}

public void printRandomNumber() {

System.out.println("The next random number is: " + iter.next());
}

public boolean shouldReset() {
return !iter.hasNext();
}

public void reset() {
List<Integer> list = new ArrayList<>(IntStream.rangeClosed(min, max).boxed().collect(Collectors.toList()));
Collections.shuffle(list);
iter = list.iterator();
}
}

Generation of 4 non repeating random numbers using arrays in java

Well, yes, numbers can be repeated while being random. You need to do your own logic to validate if they're already on the array, this can be done with the following code:

In the code I used an array of 10 elements to observe there aren't repeated numbers even on that situation.

import java.util.Random;

public class RandomNumbersNoRepeating {
public static void main(String[] args) {
int array[] = new int[10];
Random random = new Random();

//Fills the array
for (int i = 0; i < array.length; i++) {
boolean found = false;
int r = 0;
do {
found = false;
r = random.nextInt(10) + 1;
//Here we check if the number is not on the array yet
for (int j = 0; j < array.length; j++) {
if (array[j] == r) {
found = true;
break;
}
}
} while (found);

array[i] = r;
}

//Prints the array
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}

Another possible solution, as given in a comment could be to shuffle an array from 1-10, and get the first four numbers

Creating random numbers with no duplicates

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:

if (max < numbersNeeded)
{
throw new IllegalArgumentException("Can't ask for more numbers than are available");
}
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.

Non repeating random numbers

Fisher-yates shuffle algorithm is the way to go. Its efficient for shuffling.
and it works in linear time.

here is algo

To shuffle an array a of n elements:
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]

and the code

for(int i=VALUES.length-1; i>0; i--){
int rand = (int) (Math.random()*i);
char temp = VALUES[i];
VALUES[i] = VALUES[rand];
VALUES[rand] = temp;
}

How to generate random numbers with non-repeating digits in Java?

How about creating a loop that checks if the generated random number meets your requirements.

final Random rnd = new Random();
int n;
do {
n = rnd.nextInt(1000);
} while(containsRepeatingDigits(n));

containsRepeatingDigits can look like this:

boolean containsRepeatingDigits(final int n) {
final boolean digits[] = new boolean[10];
for(char c : String.valueOf(n).toCharArray()) {
final int i = c-'0';
if(digits[i])
return true;
digits[i] = true;
}
return false;
}


Related Topics



Leave a reply



Submit