JavaScript Simulazione di eventi con probabilità diverse

Esempio

A volte potresti dover solo simulare un evento con due risultati, magari con probabilità diverse, ma potresti trovarti in una situazione che richiede molti risultati possibili con probabilità diverse. Immaginiamo che tu voglia simulare un evento che abbia sei risultati ugualmente probabili. Questo è abbastanza semplice.

function simulateEvent(numEvents) {
    var event = Math.floor(numEvents*Math.random());
    return event;
}

// simulate fair die
console.log("Rolled a "+(simulateEvent(6)+1));  // Rolled a 2

Tuttavia, potresti non volere risultati ugualmente probabili. Supponi di avere una lista di tre risultati rappresentati come una serie di probabilità in percentuali o multipli di probabilità. Un esempio del genere potrebbe essere un dado ponderato. È possibile riscrivere la funzione precedente per simulare tale evento.

function simulateEvent(chances) {
    var sum = 0;
    chances.forEach(function(chance) {
        sum+=chance;
    });
    var rand = Math.random();
    var chance = 0;
    for(var i=0; i<chances.length; i++) {
        chance+=chances[i]/sum;
        if(rand<chance) {
            return i;
        }
    }
    
    // should never be reached unless sum of probabilities is less than 1
    // due to all being zero or some being negative probabilities
    return -1;
}

// simulate weighted dice where 6 is twice as likely as any other face
// using multiples of likelihood
console.log("Rolled a "+(simulateEvent([1,1,1,1,1,2])+1));  // Rolled a 1

// using probabilities
console.log("Rolled a "+(simulateEvent([1/7,1/7,1/7,1/7,1/7,2/7])+1));  // Rolled a 6

Come probabilmente avrai notato, queste funzioni restituiscono un indice, così potresti avere risultati più descrittivi memorizzati in un array. Ecco un esempio.

var rewards = ["gold coin","silver coin","diamond","god sword"];
var likelihoods = [5,9,1,0];
// least likely to get a god sword (0/15 = 0%, never),
// most likely to get a silver coin (9/15 = 60%, more than half the time)

// simulate event, log reward
console.log("You get a "+rewards[simulateEvent(likelihoods)]);  // You get a silver coin