Random Array Generation with No Duplicates

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.

How do I create a list of random numbers without duplicates

This will return a list of 10 numbers selected from the range 0 to 99, without duplicates.

import random
random.sample(range(100), 10)

With reference to your specific code example, you probably want to read all the lines from the file once and then select random lines from the saved list in memory. For example:

all_lines = f1.readlines()
for i in range(50):
lines = random.sample(all_lines, 40)

This way, you only need to actually read from the file once, before your loop. It's much more efficient to do this than to seek back to the start of the file and call f1.readlines() again for each loop iteration.

Random array generation with no duplicates

First of all rand() is generatig random numbers but not wihout duplicates.

If you want to generate a random array without duplicates the rand() method is not working at all.

Let say you want to generate an array of 1000 numbers. In the best case let say you generated the first 999 numbers without duplicates and last think to do is generating the last number. The probability of getting that number is 1/1000 so this is almost going to take forever to get generated. In practice only 10 numbers makes a big trouble.

The best method is to generate all your numbers by incrementation (or strictly monotonic sequence) is shuffle them. In this case there will be no duplicates

Here is an exemple on how to do it with 10 numbers. Even with 1000 numbers it's working.

Note: Suffle function from Jhon Leehey's answer.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void shuffle(int *arr, size_t n)
{
if (n > 1)
{
size_t i;
srand(time(NULL));
for (i = 0; i < n - 1; i++)
{
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
int t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
}

int main()
{
int i;
int arr[10];
for (i=0; i<10; i++){
arr[i] = i;
}
shuffle(arr, 10);
for (i=0; i<10; i++){
printf("%d ", arr[i]);
}
}

How can I make a random array with no repeats?

There are two ways you could achieve this.

  1. Store an array of values already spun. Then, when you generate a new number, check if it's in the array of spun numbers. If it is, generate a new number and check again, until you get a number which isn't in the array. Otherwise, add it to the array.

  2. Generate an array of all the valid numbers up front, as you are doing. Then, every time you spin a number, remove it from that array. That way, the next time you 'spin' you will be only selecting from values which haven't been spun already.

  3. Generate an array of all the valid numbers up front, and then sort it randomly. Then all you have to do is keep taking the first item in the array.

In order, Option 3. is the most elegant, but it has the downside that someone with a console open could potentially see exactly what number is coming next! Option 2 is the next best, and if the user is allowed to know that a number can't come up twice, they can't 'cheat' by seeing the remaining available numbers. Option 1 is the least efficient - because it means your code will need to do more and more work to try and find a 'free' number.

Honestly, if your game needs to be at all secure from hacking, then you would not want to generate any random numbers client side anyway, so if this is just for a bit of fun, it won't really matter which method you use. If you are writing it for a gambling website, first let me know which one so I can make a fortune, and then move your logic to the server.

So here is an example of Option 2. approach

<!DOCTYPE html>
<html>
<head>
<script>

var numbers = []; // this array will store the available numbers..

function generateNumbers()
{
// populate the available numbers however you need to..
for(var i=0; i<360; i+=30)
{
numbers.push(i);
}
}

function spin()
{
if(numbers.length==0)
{
// then we've used up all available numbers..start new game or whatever you need to do..
alert("starting again");
generateNumbers();
}
var rand = Math.floor(Math.random()*numbers.length); // select an index randomly based on the number of remaining available numbers..
var num = numbers[rand];
numbers.splice(rand,1); // remove the number we selected so it can't be selected next time..
document.getElementById("number").innerHTML = num;
}

</script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="number"></div>
</body>
</html>

And Option 3. below. The main difference is that you can just shift() the next value instead of having to select randomly.

<!DOCTYPE html>
<html>
<head>
<script>

var numbers = [];

function generateNumbers()
{
for(var i=0; i<360; i+=30)
{
numbers.push(i);
}
function sort(a,b)
{
return (Math.random()>0.5)? -1 : 1;
}
numbers.sort(sort);
}

function spin()
{
if(numbers.length==0)
{
alert("starting again");
generateNumbers();
}
var num = numbers.shift();
document.getElementById("available").innerHTML = "Available:" + numbers.join(",");
document.getElementById("number").innerHTML = "Selected:" + num;
}

</script>
</head>
<body>
<button onclick="spin()">SPIN</button>
<div id="available"></div>
<div id="number"></div>
</body>
</html>

Hopefully that gives you an idea of how you could incorporate this into your code.

how generate a random number array that have no duplicate values in java

Try replacing the i with a d in the line

if (arr[d]==val) {

That should do the trick!



Related Topics



Leave a reply



Submit