3

When I call this statement 4 times in a loop, it gives me duplicate random numbers.

var a = (parseInt(Math.random() * 4))+1

For example, sometimes it gives me 1,3,2,4 (fine!!), but sometimes it produes like 1, 3, 1,4 etc.

How I make sure that when my loop runs 4 times, I get unique set everytime

8
  • 1
    Loop until you don't have duplicates. Commented Oct 19, 2013 at 13:18
  • store them in an array and validate your function's out put against the "seen before" values. Commented Oct 19, 2013 at 13:19
  • The reason it is called "random" is because it generates (sort of) random numbers. There is no guarantee that they are going to be unique. Commented Oct 19, 2013 at 13:20
  • So you have a collection of numbers which you want to have in a random order? Commented Oct 19, 2013 at 13:22
  • 1
    don't loop until there are no duplicates anymore. This loop possibly runs forever. If you get a duplicate number N you could possibly just take the N+1 number or the N+2 if also N+1 is a duplicate and so on.... Commented Oct 19, 2013 at 13:27

6 Answers 6

4

Shuffling a pre-filled array would be a good solution:

→ jsBin.com

// shuffle function taken from here
// http://stackoverflow.com/a/2450976/603003
alert( shuffle( [1,2,3,4] ) );

Another apporach consists in the following function:

→ jsFiddle

function gen4Numbers() {
    var numbers = [];
    while (numbers.length < 4) {
        var newNr = (parseInt(Math.random() * 4))+1;
        if (numbers.indexOf(newNr) == -1) {
            numbers.push(newNr);
        }
    }
    return numbers;
}
alert(gen4Numbers());

You should be warned that there is a very probability that this code will loop forever.

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

4 Comments

var lowerno=Math.floor(math.random*4);
Why not fill an array with [1,2,3,4] and shuffle it. This will remove the risk of an endless loop.
@t.niese I've added that approach.
@ComFreek - You approach of shuffling the array helped me out. Thanks :)
4

You need to buffer your answers, but a much better way is to pre-compute them.

So for example you want random integers from 1 to 4 and unique, this is the same thing as randomly sorting an array of values from 1 to 4

for the general case:

// numbers of values
var n = 10;

// make initially sorted array
var arr = [];
for (var i=1; i<=n; ++i) { arr.push(i); }

// randomly sort the array
arr.sort(function () { return Math.random() - 0.5; });

now arr will have all the numbers from 1 to 10 in a random order, so if you want 4 unique random numbers in that range they are in arr[0], arr[1] arr[2], arr[3]

make n = 4 and you have your problem solved

Comments

2

i am using time

var d = new Date(); 
var uniqId = d.getTime();

Comments

1

Store the numbers in an array, and each time check if the number was generated before.

If you aren't generating a lot of numbers, this is pretty fast since you don't have to

loop a lot.

============= Edit 1 =============

However, if you have to generate a lot of random numbers, I suggest putting an array of

all the numbers, shuffling it, and then taking the first n numbers that you need.

Array shuffling can be found here:

http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array

1 Comment

I would have suggested an object. Objects have faster lookups than arrays, I believe.
0

In case you want a huge set of numbers, you should store every distinct number, then pick one up every iteration of the loop.

var maxnB = 1000; // or 4
var list = [];

for (var i = 1; i <= maxNb; ++i) // store all number in a list [1, 2, 3, ... , maxNb]
   list.push(i);

while (list.length > 0)
{
   var pos = (parseInt(Math.random() * list.length))

   var myNumber = list[pos];  // get your unique random number
   list[pos] = list[list.length - 1]; // replace the number used with last number 
   list.pop(); //remove last number, decrease list.length by 1

   // do something with your new number
}

Doing this, you have a 0 probability of looping forever, and if the pop() method and [] operator has a o(1) time complexity access, it will improve the time processing, instead of looking for your number in the buffer list every time you got a new number to check.

Comments

0

do this.

for( i = 0; i< 4; i++)
{
  num = Math.floor((Math.random() * 3) + 1);

  if(randomArray.indexOf(num)<0)
  {
    randomArray[i]=num;
  }//endif
  else
  {
    i=i-1;
  }//endElse
}//endForLoop

basically, if a number is repeated -lets say at position 3 (randomArray[3] has same value as randomArray[atAnotherIndex], your counter goes back to 3 and do math.random again until a unique value is attained.

Comments

Your Answer

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