0

I have an array of values:

var my_arr = [/*all kinds of stuff*/]

I have a function that generates a random number, which I use as the index of an element in my_arr...

var RandomFromRange = function (min,max)
{
    return Math.floor(Math.random()*(max-min+1)+min);
};

...so I could do stuff like this:

my_arr[RandomFromRange(0,my_arr.length)];

What I want to do is to designate certain elements within my_arr as having "priority", so that RandomFromRange returns 5, say, 25% of the time, returns 4, 14% of the time, and returns any other number...

(100 - 25 - 14)/(my_arr.length - 2)

...% of the time.

As I was doing my research, I came across several posts that describe similar problems, but their answers are not in Javascript, and I, alas, don't have enough math to understand their general principles. Any advice would be appreciated.

dhilt
  • 18,707
  • 8
  • 70
  • 85
shopofolive
  • 265
  • 3
  • 15
  • 1
    If you're interested in understanding this then i recommend reading http://www.keithschwarz.com/darts-dice-coins/ which came about from this SO question: https://stackoverflow.com/questions/5027757/data-structure-for-loaded-dice – david Nov 02 '17 at 00:58
  • The javascript sources for the @david link is [here](http://www.keithschwarz.com/darts-dice-coins/js/alias.js). – dhilt Nov 02 '17 at 01:01
  • Many thanks for the references, dhilt and david. – shopofolive Nov 02 '17 at 02:11

1 Answers1

0

This may not be as exact as what you are looking for, but this certainly works. Basically this code returns a random number specified from the min and max like yours, but only after addressing the priority numbers based on the chance given.

First we gotta prioritize your priority numbers in the code. If there is no hit on your priority numbers, that is when we proceed to the normal RNG.

//priority = list of numbers as priority,
//chance = the percentage
//min and max are your parameters

var randomFromRange = function (min,max,priority,chance)
{
  var val = null; //initialize value to return
 
 for(var i = 0; i < priority.length; i++){ //loop through priority numbers
  
  var roll = Math.floor(Math.random()*100); //roll the dice (outputs 0-100)
  
  if(chance > roll){ ///check if the chance is greater than the roll output, if true, there's a hit. Less chance value means less likely that the chance value is greater than the roll output
   val = priority[i]; //make the current number in the priority loop the value to return;
   break; //if there's a hit, stop the loop.
  }
  else{
   continue; //else, keep looping through the priority list
  }
 }
 
  //if there is no hit to any priority numbers, return a number from the min and max range
 if(val == null){
  val = Math.floor(Math.random()*(max-min+1)+min);
 }
 
  //return the value and do whatever you want with it
 return val;
};

document.getElementsByTagName('body')[0].onclick = function (){
 console.log(randomFromRange(0,10,[20,30],50));
}
<!DOCTYPE html>
<html>
<body style='height: 1000px; width: 100%;'></body>
<script></script>
</html>

This code applies a single chance on all array of priority numbers. If you want individual chances for each number in the priority list, we gotta modify the structure and change parameters to a single array of objects that holds something like

var priorityList = [{num: 4, chance: 25},
                    {num: 5, chance: 12}]

etc

Abana Clara
  • 4,602
  • 3
  • 18
  • 31