Random number without repetition

14

I made a few attempts to do a function that would return random numbers that did not repeat, I made a few attempts but none succeeded, if they can show me a function that does this, I thank you.

    
asked by anonymous 23.03.2014 / 23:48

3 answers

14

The solution that occurs to me is to create an array and add the already created / drawn values to it, and look in the array if the value already exists before exporting a new one.

This solution allows you to sort values one by one as well as to sort them all at once.

var sorteados = [];
var valorMaximo = 1000;

function criarUnico() {
    if (sorteados.length == valorMaximo) {
        if (confirm('Já não há mais! Quer recomeçar?')) sorteados = [];
        else return;
    }
    var sugestao = Math.ceil(Math.random() * valorMaximo); // Escolher um numero ao acaso
    while (sorteados.indexOf(sugestao) >= 0) {  // Enquanto o numero já existir, escolher outro
        sugestao = Math.ceil(Math.random() * valorMaximo);
    }
    sorteados.push(sugestao); // adicionar este numero à array de numeros sorteados para futura referência
    return sugestao; // devolver o numero único
}

So, to sort a number just use:

criarUnico(); // que retorna um valor único

Example

    
24.03.2014 / 00:06
13

First, generate an ordered list, in this example from 1 to 1000:

var maximo = 1000;

var i, arr = [];
for (i = 0; i < maximo; i++) {
   arr[i] = i + 1;
}

Then, shuffle the numbers inside this array:

var p, n, tmp;
for (p = arr.length; p;) {
    n = Math.random() * p-- | 0;
    tmp = arr[n];
    arr[n] = arr[p];
    arr[p] = tmp;
}

You just need to get the first items of the array, in order, from 1 to the amount of results you want, since they are already shuffled randomly, and none repeats.

  

See example with results in jsFiddle

adapted response from link


If you need few values:

This technique is efficient even with few values, just in this case shorten the loop to "shuffle" only the required number of numbers:

for (p = quantidade; p;) {

In this way, only the first values, indicated by the quantidade variable, will be "scrambled".


About the algorithm

This algorithm is Fisher-Yates , as reinforced by colleague @woliveirajr in the comments, and in another question, colleague @ FabriDamazio has found an interesting analysis comparing Fisher-Yates with brute-force shuffling.

Worth a read:

  

Analysis of a Brute-Force Shuffle

    
24.03.2014 / 00:01
2

I use this solution for simplicity, since it uses the sort () method, native to the language:

var x = new Array(1000);
for(var i=1; i<1001; i++) {
    x[i] = i; 
}

x.sort(function(a,b){ return (Math.round(Math.random())-0.5); });

However, the method used by @Bacco will always be faster, since it is not necessary to recreate the array.

    
24.03.2014 / 19:42