2

Ok so i need to create four randomly generated numbers between 1-10 and they cannot be the same. so my thought is to add each number to an array but how can I check to see if the number is in the array, and if it is, re-generate the number and if it isnt add the new number to the array?

so basically it will go,

1.create new number and add to array 2.create second new number, check to see if it exist already, if it doesn't exist, add to array. If it does exist, re-create new number, check again etc... 3.same as above and so on.

2
  • Which of those steps are you having trouble with? Commented Aug 12, 2011 at 19:57
  • You already know what to do. All you need to do is give it a try. And if somehow it doesn't work post your code here for people to look and help you. Commented Aug 12, 2011 at 19:59

7 Answers 7

10

You want what is called a 'random grab bag'. Consider you have a 'bag' of numbers, each number is only represented once in this bag. You take the numbers out, at random, for as many as you need.

The problem with some of the other solutions presented here is that they randomly generate the number, and check to see if it was already used. This will take longer and longer to complete (theoretically up to an infinite amount of time) because you are waiting for the random() function to return a value you don't already have (and it doesn't have to do that, it could give you 1-9 forever, but never return 10).

There are a lot of ways to implement a grab-bag type solution, each with varying degrees of cost (though, if done correctly, won't ever be infinite).

The most basic solution to your problem would be the following:

var grabBag = [1,2,3,4,5,6,7,8,9,10];

// randomize order of elements with a sort function that randomly returns -1/0/1
grabBag.sort(function(xx,yy){ return Math.floor(Math.random() * 3) - 1; })

function getNextRandom(){
    return grabBag.shift();
};

var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
    console.log(getNextRandom());
}

This is of course destructive to the original grabBag array. And I'm not sure how 'truly random' that sort is, but for many applications it could be 'good enough'.

An slightly different approach would be to store all the unused elements in an array, randomly select an index, and then remove the element at that index. The cost here is how frequently you are creating/destroying arrays each time you remove an element.

Sign up to request clarification or add additional context in comments.

1 Comment

Removing the chosen item from the pool of remaining choices is absolutely the way to go. Any algorithm that requires a test for uniqueness will have a really terrible worst-case execution time.
3

Here are a couple versions using Matt's grabBag technique:

function getRandoms(numPicks) {
    var nums = [1,2,3,4,5,6,7,8,9,10];
    var selections = [];

    // randomly pick one from the array
    for (var i = 0; i < numPicks; i++) {
        var index = Math.floor(Math.random() * nums.length);
        selections.push(nums[index]);
        nums.splice(index, 1);
    }
    return(selections);
}

You can see it work here: http://jsfiddle.net/jfriend00/b3MF3/.

And, here's a version that lets you pass in the range you want to cover:

function getRandoms(numPicks, low, high) {
    var len = high - low + 1;
    var nums = new Array(len);
    var selections = [], i;
    // initialize the array
    for (i = 0; i < len; i++) {
        nums[i] = i + low;
    }

    // randomly pick one from the array
    for (var i = 0; i < numPicks; i++) {
        var index = Math.floor(Math.random() * nums.length);
        selections.push(nums[index]);
        nums.splice(index, 1);
    }
    return(selections);
}

And a fiddle for that one: http://jsfiddle.net/jfriend00/UXnGB/

Comments

2

Use an array to see if the number has already been generated.

var randomArr = [], trackingArr = [],
    targetCount = 4, currentCount = 0,
    min = 1, max = 10,
    rnd;

while (currentCount < targetCount) {
    rnd = Math.floor(Math.random() * (max - min + 1)) + min;
    if (!trackingArr[rnd]) {
        trackingArr[rnd] = rnd;
        randomArr[currentCount] = rnd;
        currentCount += 1;
    }
}

alert(randomArr); // Will contain four unique, random numbers between 1 and 10.

Working example: http://jsfiddle.net/FishBasketGordo/J4Ly7/

1 Comment

This could potentially never complete, particularly if N is large and your selection of M units approaches N. See my comment in @Joseph's answer.
1
var a = [];
for (var i = 0; i < 5; i++) {
  var r = Math.floor(Math.random()*10) + 1;
  if(!(r in a))
    a.push(r);
  else
    i--;
}

That'll do it for you. But be careful. If you make the number of random numbers generated greater than the may number (10) you'll hit an infinite loop.

3 Comments

@PaulPRO lol was using it while bug fixing but decided to nix that feature :P (would have incremented errors and displayed it later)
This could take a very long time to finish, depending on how many numbers you want and how lucky you are. It could theoretically return 1 every time, and your loop would never terminate. Now, practically speaking, this won't likely ever happen with the data you have here. But, if you have a lot of numbers, and you want a significant portion of those numbers, it could take a very very long time to complete.
@Matt indeed, but It's simple enough and won't realistically be a problem. I like your idea of a random sort better though.
0

I'm using a recursive function. The test function pick 6 unique value between 1 and 9.

//test(1, 9, 6);

function test(min, max, nbValue){
    var result = recursValue(min, max, nbValue, []);
    alert(result);
}

function recursValue(min, max, nbValue, result){
    var randomNum = Math.random() * (max-min);
    randomNum = Math.round(randomNum) + min;

    if(!in_array(randomNum, result)){
        result.push(randomNum);
        nbValue--;
    }

    if(nbValue>0){
        recursValue(min, max, nbValue, result);
    }
    return result;
}

function in_array(value, my_array){
    for(var i=0;i< my_array.length; i++){
        if(my_array[i] == value){
            console.log(my_array+" val "+value);
            return true;   
        }        
    }
    return false;
}

Comments

0

Here is a recursive function what are you looking for.

"howMany" parameter is count of how many unique numbers you want to generate.
"randomize" parameter is biggest number that function can generate.

for example : rand(4,8) function returns an array that has 4 number in it, and the numbers are between 0 and 7 ( because as you know, Math.random() function generates numbers starting from zero to [given number - 1])

var array = [];
var isMatch= false;
function rand(howMany, randomize){
     if( array.length < howMany){
    var r = Math.floor( Math.random() * randomize );
    for( var i = 0; i < howMany; i++ ){
        if( array[i] !== r ){
           isMatch= false;
           continue;
            } else {
           isMatch= true;
           break;
        }
    }
    if( isMatch == false ){
       array.push(r);
           ran(howMany, randomize);
    }
        ran(howMany, randomize);
    return array;
     }
}

Comments

0

In your answer earlier, you do have a small bug. Instead of

var originalLength = grabBag.length;
for(var i = 0; i < originalLength .length; i++){
    console.log(getNextRandom());
}

I believe you meant:

var originalLength = grabBag.length;
for(var i = 0; i < originalLength; i++){
    console.log(getNextRandom());
}

Thanks.

1 Comment

I edited the answer. Next time please suggest an edit if it is only correcting a typo.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.