 pair of random unique number

skoff
msg:4444940  1:23 am on Apr 25, 2012 (gmt 0)  hi, i need an array that will contain 20 numbers. The numbers will be between 1 and 10. And i want these number to be there maximum 2 times so i will have two times each number in my array. But i need them to be insert randomly so they dont be a the same place in my array every. I tried something but it doesnt work. Heres my code :
var Cards = new Array();
while (Cards.length < 20) {
var rndNum = Math.floor(Math.random() * 10) + 1; var found = false; var count = 0;
for (i=0;i<Cards.length;i++) { if (Cards[i] == rndNum) { count +=1; if (count<2) { Cards[Cards.length] = rndNum; } else { found = true; break; } } } if(!found && count<2)Cards[Cards.length] = rndNum; } here's an output of what i get so far : 4,6,1,2,1,8,4,1,5,5,1,8,3,4,10,1,7,1,8,5 thanks for your help

shingokko
msg:4444958  1:57 am on Apr 25, 2012 (gmt 0)  You just need to alter the code in the for loop a little bit so that the loop will only be used to find whether there are more than or equal to two of the same number. You just need to check the value of count right after the loop and add the number to the array if there are less than two of the same number in the array. Here's how I would change the code inside the while loop:
for (var i = 0; i < Cards.length; i++) { if (Cards[i] == rndNum) { count++; if (count >= 2) { break; } } }
if (count < 2) { Cards[Cards.length] = rndNum; }
Hope this works.

skoff
msg:4444962  2:06 am on Apr 25, 2012 (gmt 0)  yep its working! Thanks for your help :)

Fotiman
msg:4445401  4:16 pm on Apr 25, 2012 (gmt 0)  The problem with both of these approaches is that there is the potential for this to never complete (theoretically). You are generating random numbers, then determining if that number has been used already, and if so, ignoring that iteration and generating again, which is inefficient. Imagine if the random number generated was the same over and over. You have a fixed number of items that you need to randomize, which is the following set of numbers: 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10 So instead of generating a random number from 1 to 10, generate a random number from 1 to the size of the input, and then use that random number as the index to retrieve a number from your input data. For example: var input = [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10], output = [], rndNum; while (input.length > 1) { rndNum = Math.floor(Math.random() * (input.length  1)); output.push(input.splice(rndNum, 1)); } output.push(input.splice(0,1));

 Output will now contain an array of random numbers pulled from input (and input will be empty as a result of using the slice operation to pull out values from the array). This reduces the number of random numbers that needs to be generated to 19 (the number of items in your input minus 1), and there's no duplication issues. More efficient, and smaller code. :)

astupidname
msg:4445822  6:13 am on Apr 26, 2012 (gmt 0)  Or another simple option: var cards = [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10].sort( function(){ return Math.random()0.5; } ); alert(cards); 


Fotiman
msg:4446015  2:38 pm on Apr 26, 2012 (gmt 0)  That's a neat trick! :) However, it's slightly less efficient, only because it may require iterating through an array several times as it moves elements up and down in the array. This can be demonstrated with this: var c = 0, cards = [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10].sort( function(){ c++; return Math.random()0.5; } ); alert('Number of calls to Math.random = ' + c);

 For me, this is averaging around 54 calls to Math.random() with that array. So it's neat and compact, but slightly less efficient. I also think it's less obvious what it's doing, so adds complexity, even though it's a smaller chunk of code. Still, great to see another way to skin the cat. :)


