0

I have an annoying script I can't complete.

I need 32 non-repeating numbers out of a possible 0-64 number set. Every time I try to create a loop to check the new random number against all the numbers in the array I end up with nothing, or an infinite loop.

I'm stumped :(

flyagaricus
  • 119
  • 1
  • 2
  • 8
  • 2
    possible duplicate of [How to randomize a javascript array?](http://stackoverflow.com/questions/2450954/how-to-randomize-a-javascript-array) – Patashu May 24 '13 at 06:02
  • possible duplicate of [Random non-repeating number generation in javascript between two limits](http://stackoverflow.com/questions/16728297/random-non-repeating-number-generation-in-javascript-between-two-limits) – Cameron Skinner May 24 '13 at 06:12
  • The infinite loop is OK in that case, making it a [las vegas algorithm](http://en.wikipedia.org/wiki/Las_Vegas_algorithm). Though of course it is not optimal, it would be acceptable. – Bergi May 26 '13 at 22:19

2 Answers2

3

Try this:

var keys = [], numbers = [], x, total = 0;
while(total < 32) {
    x = Math.floor(Math.random() * 64);
    // way faster that looping through the array to check if it exists
    if(keys[x] == undefined) { 
        keys[x] = 1;
        numbers.push(x);
        total++;
    }
}
console.log(numbers);

Working Demo

techfoobar
  • 65,616
  • 14
  • 114
  • 135
  • This will never return 64 but it will return 0. Math random is 0 inclussive to 1 exclusive - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/random - that page also has good suggestions on how to implement random int between x and y – Peter Ajtai May 24 '13 at 06:20
  • Thanks, that's close, but all the numbers in the array are sequential. Is there a quick way to randomize them? – flyagaricus May 24 '13 at 06:23
  • @PeterAjtai - The OP needed the numbers between 0 and 64 specifically. Hence the floor call. – techfoobar May 24 '13 at 06:23
  • @flyagaricus - For that, you can directly use http://stackoverflow.com/questions/2450954/how-to-randomize-a-javascript-array – techfoobar May 24 '13 at 06:24
  • @techfoobar you are returning number between 0 and 63 not 0 and 64 – Peter Ajtai May 24 '13 at 06:25
  • 1
    @PeterAjtai - You're right. This will never return 64. Answer corrected. – techfoobar May 24 '13 at 06:25
  • @flyagaricus just print them out inside the if loop instead of at the end to see them in their random order – Peter Ajtai May 24 '13 at 06:27
  • Sorry, I should have been more specific - I need 32 numbers from 0-63 as array indexing is fine - as long as there are 32 indexes. – flyagaricus May 24 '13 at 06:27
  • +1 - you could move pushing the number onto the array inside the if statement, and that way you don't have to loop over keys at the end. – Peter Ajtai May 24 '13 at 06:36
  • @PeterAjtai - Can't believe i din think of that! Tks for the pointer. – techfoobar May 24 '13 at 06:41
0

This code will generate a non repeating random number between 0 and whatever number you give it and will start over when it has been called the amount of the number you give it.

Give it a try:

let randomNumber = function (max) {
    let min = 0, prevIndexes = [];
    function exec(max2) {
        max = max || max2;
        let result = Math.floor(Math.random() * (max - min + 1) + min);
        if (prevIndexes) {
            if (prevIndexes.length - 1 === max) {
                clear();
            }
            let foundDouble, eqPrevInn = true;
            while (eqPrevInn) {
                foundDouble = false;
                result = Math.floor(Math.random() * (max - min + 1) + min);
                for (let i = 0, l = prevIndexes.length; i < l; i++) {
                    if (result === prevIndexes[i]) {
                        foundDouble = true;
                        break;
                    }
                }
                if (!foundDouble) {
                    eqPrevInn = false;
                }
            }
        }
        prevIndexes.push(result);
        console.log(prevIndexes);
        return result;

    }

    let clear = function () {
        if (prevIndexes) {
            prevIndexes = [];
            //             console.log('prevIndexes has been cleared');
        }
        else {
            //             console.log('already clear');
        }
    }
    return {
        exec: exec,
        clear: clear
    }
};

let random32 = randomNumber(32/*range*/).exec;

for (let i = 0; i <= 32; i++) {
    random32();
}