function weightedChoice(array, weights) {
let s = weights.reduce((a, e) => a + e);
let r = Math.random() * s;
return array.find((e, i) => (r -= weights[i]) < 0);
}
let randomArray =
Array.apply(null, Array(32)).
map(() => weightedChoice([5, 95], [75, 25]));
console.log(JSON.stringify(randomArray));
EDIT: Patrick was a bit faster than me, so I'll endorse his answer, and I'll just add that you don't absolutely need the sum to be 1, you can normalise the weight by finding out the sum by yourself.
EDIT EDIT: If you are really worried about performance in the case of needing many random values with the same weights, this would do better (by precalculating as much as possible):
class WeightedSampler {
constructor(elements, weights) {
this.total = 0;
this.elements = Array.from(elements);
this.cweights = weights.map(weight => this.total += weight);
}
get() {
let random = Math.random() * this.total;
return this.elements.find((element, index) => random < this.cweights[index]);
}
}
const sampler = new WeightedSampler(["M", "I", " "], [3, 9, 1]);
let randomArray = Array.apply(null, Array(32)).map(() => sampler.get());
console.log(randomArray.join(""));