Go Back   CodingForums.com > :: Client side development > JavaScript programming

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 06-29-2012, 02:02 PM   PM User | #1
meridian
New Coder

 
Join Date: Jun 2012
Posts: 26
Thanks: 25
Thanked 0 Times in 0 Posts
meridian is an unknown quantity at this point
How to stop randomizing Array repeats

Hi

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.

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Japanese Flashcards</title>
</head>

<body>

<h1>Japanese Flashcards</h1>
<p id="japanese"></p>
<p id="english">&nbsp;</p>

<button onclick="showEnglish()">Answer</button>
<button onclick="nextWord()">Next word</button>

<script type="text/javascript">
var words = 
[
    ["taberu",  "to eat"], 
    ["yomu",    "to read"], 
    ["iku",     "to go"], 
	["kaku",     "to write"],
	["yomu",    "to drink"],
	
];
var  cnt = Math.floor((Math.random()*5)+0); 
document.getElementById("japanese").innerHTML=words[cnt][0];

function showEnglish()
{    
	document.getElementById("english").innerHTML = words[cnt][1];    
}	

function nextWord()
{
    cnt = Math.floor((Math.random()*5)+0); 
	

    document.getElementById("japanese").innerHTML = words[cnt][0] 
    document.getElementById("english").innerHTML='&nbsp;';
}


</script>
</body>
</html>
meridian is offline   Reply With Quote
Old 06-29-2012, 02:29 PM   PM User | #2
vwphillips
Senior Coder

 
Join Date: Mar 2005
Location: Portsmouth UK
Posts: 4,355
Thanks: 3
Thanked 458 Times in 445 Posts
vwphillips is a jewel in the roughvwphillips is a jewel in the roughvwphillips is a jewel in the rough
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Japanese Flashcards</title>
</head>

<body>

<h1>Japanese Flashcards</h1>
<p id="japanese"></p>
<p id="english">&nbsp;</p>

<button onclick="showEnglish()">Answer</button>
<button onclick="nextWord()">Next word</button>

<script type="text/javascript">
var words =
[
    ["taberu",  "to eat"],
    ["yomu",    "to read"],
    ["iku",     "to go"],
	["kaku",     "to write"],
	["yomu1",    "to drink"],

];
var  cnt = Math.floor((Math.random()*5)+0);
document.getElementById("japanese").innerHTML=words[cnt][0];

function showEnglish()
{
	document.getElementById("english").innerHTML = words[cnt][1];
}

function nextWord()
{
    var ncnt = Math.floor((Math.random()*5)+0);
    while (ncnt==cnt){
     ncnt = Math.floor((Math.random()*5)+0);
    }
    cnt=ncnt;
    document.getElementById("japanese").innerHTML = words[cnt][0]
    document.getElementById("english").innerHTML='&nbsp;';
}


</script>
</body>
</html>
__________________
Vic

God Loves You and will never love you less.

http://www.vicsjavascripts.org.uk/

If my post has been useful please donate to http://www.operationsmile.org.uk/
vwphillips is offline   Reply With Quote
Users who have thanked vwphillips for this post:
meridian (06-30-2012)
Old 06-30-2012, 12:27 AM   PM User | #3
meridian
New Coder

 
Join Date: Jun 2012
Posts: 26
Thanks: 25
Thanked 0 Times in 0 Posts
meridian is an unknown quantity at this point
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.
meridian is offline   Reply With Quote
Old 06-30-2012, 01:11 AM   PM User | #4
007julien
Regular Coder

 
Join Date: May 2012
Location: France
Posts: 115
Thanks: 0
Thanked 17 Times in 15 Posts
007julien is an unknown quantity at this point
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..
007julien is offline   Reply With Quote
Users who have thanked 007julien for this post:
meridian (06-30-2012)
Old 06-30-2012, 02:42 AM   PM User | #5
felgall
Master Coder

 
felgall's Avatar
 
Join Date: Sep 2005
Location: Sydney, Australia
Posts: 5,462
Thanks: 0
Thanked 499 Times in 491 Posts
felgall is a jewel in the roughfelgall is a jewel in the roughfelgall is a jewel in the rough
Quote:
Originally Posted by 007julien View Post
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.
__________________
Stephen
Learn Modern JavaScript - http://javascriptexample.net/
Helping others to solve their computer problem at http://www.felgall.com/
felgall is offline   Reply With Quote
Users who have thanked felgall for this post:
meridian (06-30-2012)
Old 06-30-2012, 03:37 AM   PM User | #6
meridian
New Coder

 
Join Date: Jun 2012
Posts: 26
Thanks: 25
Thanked 0 Times in 0 Posts
meridian is an unknown quantity at this point
007julien - I think that is an interesting solution. I will need to study your code though to get my head around it more.

felgall - That would solve my apparent lack of randomness. I guess the myArray.sort function is more suited to a randomized incremental array though.

Thanks for that guys.
meridian is offline   Reply With Quote
Old 06-30-2012, 08:14 AM   PM User | #7
Philip M
Supreme Master coder!

 
Philip M's Avatar
 
Join Date: Jun 2002
Location: London, England
Posts: 17,043
Thanks: 197
Thanked 2,412 Times in 2,390 Posts
Philip M has a spectacular aura aboutPhilip M has a spectacular aura aboutPhilip M has a spectacular aura about
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.

Last edited by Philip M; 06-30-2012 at 08:53 AM..
Philip M is offline   Reply With Quote
Users who have thanked Philip M for this post:
meridian (06-30-2012)
Old 06-30-2012, 10:26 AM   PM User | #8
meridian
New Coder

 
Join Date: Jun 2012
Posts: 26
Thanks: 25
Thanked 0 Times in 0 Posts
meridian is an unknown quantity at this point
Philip M - that works perfectly. Just what I was trying to do.

Thanks heaps
meridian is offline   Reply With Quote
Old 06-30-2012, 04:59 PM   PM User | #9
007julien
Regular Coder

 
Join Date: May 2012
Location: France
Posts: 115
Thanks: 0
Thanked 17 Times in 15 Posts
007julien is an unknown quantity at this point
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?'&nbsp;':'')+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..
007julien is offline   Reply With Quote
Users who have thanked 007julien for this post:
meridian (07-01-2012)
Old 06-30-2012, 05:16 PM   PM User | #10
Philip M
Supreme Master coder!

 
Philip M's Avatar
 
Join Date: Jun 2002
Location: London, England
Posts: 17,043
Thanks: 197
Thanked 2,412 Times in 2,390 Posts
Philip M has a spectacular aura aboutPhilip M has a spectacular aura aboutPhilip M has a spectacular aura about
For an unbiased array shuffle routine see

http://www.codingforums.com/showthread.php?p=1239568 (author Lerura)
__________________

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.
Philip M is offline   Reply With Quote
Users who have thanked Philip M for this post:
meridian (07-01-2012)
Old 07-01-2012, 04:48 AM   PM User | #11
meridian
New Coder

 
Join Date: Jun 2012
Posts: 26
Thanks: 25
Thanked 0 Times in 0 Posts
meridian is an unknown quantity at this point
Wow. It's amazing the difference between the different methods used. An effective demonstration. Thanks.
meridian is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 07:11 AM.


Advertisement
Log in to turn off these ads.