Weighted Random Number Generation In Javascript
Solution 1:
I would do what you want to do with loops. Total up the max number of plays for any song in the list, then reverse the probability by calculating a number that is reverse weighted and choosing from the reverse total. Something like this:
functionpickRandom(myArray) {
var maxPlays = 0, reverseTotPlays = 0, ipl, picked, revAcc = 0;
// Empty array or bad input paramif (!myArray || !myArray.length) {
return -1;
}
// Calculate the max plays for any song in the listfor (ipl = 0; ipl < myArray.length; ++ipl) {
if (myArray[ipl].plays > maxPlays) {
maxPlays = myArray[ipl].plays;
}
}
maxPlays += 1; // Avoid excluding max songs// Calculate the reverse weighted total playsfor (ipl = 0; ipl < myArray.length; ++ipl) {
reverseTotPlays += maxPlays - myArray[ipl].plays;
}
// Choose a random number over the reverse weighted spectrum
picked = ~~(Math.random() * reverseTotPlays);
// Find which array member the random number belongs tofor (ipl = 0; ipl < myArray.length; ++ipl) {
revAcc += maxPlays - myArray[ipl].plays;
if (revAcc > picked) {
return ipl;
}
}
return myArray.length - 1;
}
var pp = [{ plays: 3 }, { plays: 1 }, { plays: 2 }];
console.log(pickRandom(pp));
Working JSFiddle Here
Edit: If you don't want a zero probability on playing the songs that have been played the max times in the list, add +1 to maxPlays after the first loop.
Solution 2:
It's probably easiest to do a two-step selection, start by selecting a random song, then see if that song passes a second test designed to preferentially select less-played songs. If it fails that second test, discard it and start the whole process again.
An example (forgive me if I've made a mistake, it's been a long time since I did any javascript):
functionpickRandom(){
var candidate;
while (true){
candidate = songs[Math.round(Math.random() * (songs.length - 1))];
//largest_played is the largest number of plays of any one song// I've magiced it out of nowhere here, find it in a manner that// suits your program.if ( candidate.plays/largest_played < math.random() ){
return candidate;
}
}
}
Obviously, there's a lot of gloss and error checking missing, but it should be enough to get you started.
Post a Comment for "Weighted Random Number Generation In Javascript"