Just wondering when randomizing values in an array how I can prevent the same value being randomly generated twice in a row (ie value stays the same). In my vocab flashcards script when clicking 'next word' it sometimes just returns the same word. Note: I'm not looking to randomize the array and then step through it incrementally. It's ok if the word pops up again soon in the stack.
Thanks vwphillips. That makes sense but interestingly when I tested it it still occasionally returns the same word (the word stays the same). I'm not sure why. Also, it doesn't seem to be particularly random, but perhaps it is just because it is a small data set.
An other method could consist to sort randomly the array (with a myArray.sort(function(a,b){return 0.5-Math.random();})) to take the n first elements...
But with many elements, all this methods can become very long ! A variant consists to choose progressively the elements among the remaining elements. Here is an example...
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>Random Values</title>
<style type="text/css">
body {margin:0;padding:0;font-family:Georgia;text-align:center;}
#pge {display:block;width:500px;margin:3px auto;}
p.snd {cursor:pointer;color:#909;}
</style>
</head>
<body>
<div id="pge">
<p>A simple method to choosec 50 item among 500<br>
(without sorting the whole collection)</p>
<p id="rsp"></p>
<p>Click on the page for a new generation</p>
</div>
<script type="text/javascript">
function choose(){
// With for example 500 items (from 01 to 500)
var nbrItm=500,nbrTrt=0,nbrAtr=50;// Total number of item, number of pulled items and number to be pulled
var itmLst='',itmObj={} // array and object with pulled items
do {var k=1+Math.floor(Math.random()*(nbrItm-nbrTrt));// choose of a rank among the remaining items
// Reduce k for every remainig item to take the kth, when k is null
for (var i=1;;i++) if (typeof(itmObj[i])!='number' && (--k)==0){
itmObj[i]=1;itmLst+=','+i;break;}
nbrTrt++}
while (nbrTrt!=nbrAtr);
itmLst=itmLst.substr(1).split(/,/g).sort(function(a,b){return a-b;}).join(', ');
document.getElementById('rsp').innerHTML=itmLst;
}
choose();
window.onclick=choose;
</script>
</body>
</html>
This code sort the choosing items
Last edited by 007julien; 06-30-2012 at 01:22 AM..
An other method could consist to sort randomly the array (with a myArray.sort(function(a,b){return 0.5-Math.random();})) to take the n first elements...
Using 0.75 instead of 0.5 in that calculation will produce results closer to being random. Anything less than 0.75 is biased toward the original order.
If all you want to do is prevent the same word appearing twice in succession then you could use:-
Code:
var cnt = 0;
var previous = 0;
while(cnt == previous) {
cnt = Math.floor(Math.random()*5);
}
previous = cnt;
alert (cnt); // for testing
In other words, if the generated random number is the same as the previous one, generate another one.
Not strictly random then, but good enough for the purpose. Obviously the larger the number of words the less likely a repeat anyway.
You could extend this so that the same word was not repeated in any series of three:-
Code:
var cnt = 0;
var previous = 0;
var beforethat = 0;
while ((cnt == previous) || (cnt == beforethat)) {
cnt = Math.floor(Math.random()*5);
}
beforethat = previous;
previous = cnt;
alert (cnt); // for testing
__________________
All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.
Take care. The proposed method to sort an array with a function which compare randomly two values is not right (with 0.5 and even more with 0.75) ! The values are generally not uniformly distributed in the interval [0,1) !
Code:
// The results of this method depends on the browser
mydArray.sort(function(a,b){return Math.random()-0.5)})
The following script shows the distribution obtained with the three methods (the values are grouped by 4 to smooth the distributions)
Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="cache-control" content="no-cache">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title>Random Values</title>
<style type="text/css">
body {margin:0;padding:0;font-family:Georgia;text-align:center;}
#pge {display:block;width:900px;margin:3px auto;text-align:left;font-size:9px;}
p{font-size:12px;font-weight:bold;}
.grp {font-family:"courier new";color:#fff;font-weight:500;}
.ble {padding:0px;background-color:#039;font-size:6px;}
</style>
</head>
<body>
<div id="pge">
</div>
<script type="text/javascript">
var cards=[];for (var i=0;i<52;i++) cards[i]=i;
function affiche(o){var i,j,k,g='',s=0,t;
for (i=0;i<13;i++){j=o[i];s+=j;
g+=(i<10?' ':'')+i+' <span class="ble" style="padding-left:'+((k=Math.ceil(j/3))<800?k:800)+'px" height="5px">'+j+'</span><br>';
}
document.getElementById('pge').innerHTML+='<p><span class="grp">'+g+'</span><br>Somme :'+s+'</p>';
}
var randomCard=[];for (var i=0;i<13;i++) randomCard[i]=0;
for (var i=0;i<5000;i++) {
var newCards=cards.slice(0);
newCards.sort(function(a,b){return Math.random()-0.5});
randomCard[Math.floor(newCards[0]/4)]+=1;
}
document.getElementById('pge').innerHTML+='<p>Random sort with 0.5 </p>';
affiche(randomCard);
var randomCard=[];for (var i=0;i<13;i++) randomCard[i]=0;
for (var i=0;i<5000;i++) {
var newCards=cards.slice(0);
newCards.sort(function(a,b){return Math.random()-0.75});
randomCard[Math.floor(newCards[0]/4)]+=1;
}
document.getElementById('pge').innerHTML+='<p>Random sort with 0.75 </p>';
affiche(randomCard);
var randomCard=[];for (var i=0;i<13;i++) randomCard[i]=0;
for (var i=0;i<5000;i++) randomCard[Math.floor(Math.floor(Math.random()*52)/4)]+=1;
document.getElementById('pge').innerHTML+='<p>With random number </p>';
affiche(randomCard);
</script>
</body>
</html>
Run this page on IE, Mozilla FireFox, Safari, Opera, to compare the results. Only Google Chrome semms to give uniformly distributed values with the three methods !
Last edited by 007julien; 06-30-2012 at 05:05 PM..