Random number in a range of numbers with predefined probabilities

Asked

Viewed 310 times

0

I need to create a kind of roulette where a random prize comes out:

  • the type of prize, for example 5 different prizes some better than others
  • The better the premium the lower the chance of leaving
  • the stock of premiums, take into account whether the premium is still in stock

I was thinking of organizing the values like this:

var premios = [
        { 'tipo': 'premio1', 'stock': 40, 'probabilidade': 0.5 },
        { 'tipo': 'premio2', 'stock': 40, 'probabilidade': 0.5 },
        { 'tipo': 'premio3', 'stock': 30, 'probabilidade': 0.4 },
        { 'tipo': 'premio4', 'stock': 10, 'probabilidade': 0.2 },
        { 'tipo': 'premio5', 'stock': 5, 'probabilidade': 0.1 }
    ];

I’ve been experimenting with a lot of things, I think I’ve come close to a solution, but it’s not working 100%, the odds don’t add up. I’m a little lost, someone can help?

function RandomProb () {
    var s = 0,
        pcnt = premios.length, 
        num = Math.floor(Math.random() * (1000 - 1 + 1)) + 1;

    for (var i = 0; i < pcnt; ++i) {

        range = premios[i].probabilidade * 1000;

        if (num < 1000-range && premios[i].stock) {
            premios[i].stock--; 
            return premios[i].tipo;
        }
    }
};
  • 2

    I think it would be easier to create the range in the values, for example from [0-2000] Prize 1, [4000- 4100] Prize 4, you can take a look at this other question

  • Thanks @Marcogiovanni, I get it. I think it might be a good idea.

  • 1

    simply duplicate the values with greater probability of appearing or triple quadruple depending on the import and take by Rand, goes on the same the Cod is smaller and easier

1 answer

1


After much thought and thanks to the help of the comments I managed to reach a functional solution:

var premios = [
        { 'tipo': 'premio1', 'stock': 50, 'probabilidade': 5 },
        { 'tipo': 'premio2', 'stock': 40, 'probabilidade': 4 },
        { 'tipo': 'premio3', 'stock': 30, 'probabilidade': 3 },
        { 'tipo': 'premio4', 'stock': 20, 'probabilidade': 2 },
        { 'tipo': 'premio5', 'stock': 10, 'probabilidade': 1 }
    ];


function RandomProb () {

    var aSorteio = [];

    premios = $.grep(premios, function(e){ 
        return e.stock > 0; 
    });

    premios.forEach(function (p,i) { 
            var r = Math.floor(p.probabilidade/1);
            for (var i = 0; i < r; i++) { 
                aSorteio.push(i);
            }
    });

    var g = Math.floor(Math.random() * aSorteio.length),
    p = aSorteio[g];
    if(premios[p]!=undefined){ 
        premios[p].stock--;
        return premios[p].tipo;
    }
};

Then I noticed that it is not necessary to have the probability value since at the end of the stock the premium no longer leaves. So the final solution was like this:

var premios = [
        { 'tipo': 'premio1', 'stock': 50 },
        { 'tipo': 'premio2', 'stock': 40 },
        { 'tipo': 'premio3', 'stock': 30 },
        { 'tipo': 'premio4', 'stock': 20 },
        { 'tipo': 'premio5', 'stock': 10 }
    ];


function RandomProb () {

    premios = $.grep(premios, function(e){ 
        return e.stock > 0; 
    });

    var p = Math.floor(Math.random() * premios.length);

    if(premios[p]!=undefined){ 
        premios[p].stock--;
        return premios[p].tipo;
    }
};

Browser other questions tagged

You are not signed in. Login or sign up in order to post.