Search code examples
javascriptarraysrandomprobabilityweighted

create javascript array(N) of consecutively smaller integers with the sum of 1000


I am working on a text based roll playing game, and i need to generate an array of N values of probabilities, with each consecutive value being smaller (rarer) than the one before, with the total sum equaling 1000. 1000 is important because elsewhere I have probabilities < 1%.

the array is used by this function to generate a weighted random index: with probability being the array in question

function rndProb(probability)
{

    chances = new Array();
    for(var x=0; x<probability.length ; x++)
    {
        for(var y=0; y<probability[x]; y++)
        {
        chances.push(x);
        }
    }
    var px = Math.floor(Math.random() * chances.length+1);
    return chances[px];
}

I realize this function is not efficient, but it only needs to run a few times so performance is not important. I need it to be dynamic, so i can change the number of items in the list, but all added equal 1000 ie:

var rankProb = [400,310,160,100,25,5];

something like

function probGen(arrayLength)
{
    for(var i=0;i<arrayLength;i++)
    {
         prob.push(((1000-arrayLength)/arrayLength)+1);
    }
    return prob;
}

i just can't figure the formula.


Solution

  • Start with the arithmetic sequence 1, 2, ..., N. The sum of this sequence is S = N*(N+1)/2. We can easily multiply each member of the sequence by 1000/S to get a sequence that sums to 1000. (Since you need integers, there will be a remainder, which we can just add onto the largest value.)

    In Javascript:

    function probGen(arrayLength)
    {
        var prob = [];
        var sum = arrayLength * (arrayLength + 1) / 2;
        var multiplier = Math.floor(1000 / sum);
        var remainder = 1000 - (sum * multiplier);
    
        if (sum > 1000) { return null; } // error case
    
        for (var i = arrayLength ; i > 0 ; i--)
        {
            prob.push(i * multiplier);
        }
        prob[0] += remainder;
        return prob;
    }