Looking for more elegant way to solve this simple logic task

This is part of a bigger problem I try to solve in an exercise. It looks like this:

  • x is 10 times more likely to appear than y.

  • z appears 2x less often than y.

I solved this by calculating a single unit like this:

const x = 100;
const y = 10;
const z = 5;
const unit = 100 / (x + y + z);

unit equals 0.87 So when I do (0.87) + (0.87 * 10) + (0.87 * 5) I get 100%(almost)

Then I generate a random number between 0 and 1.

const randomNumber = Math.random();
function getValue() {
    if (randomNumber <= 0.87) {
        console.log('x');
    } else if (randomNumber > 0.87 && randomNumber < 95.7) {
        console.log('y');
    } else console.log('z');
}

getValue();

If value<0.87 then I log out x, if value < 0.87+(0.087*10) I log y etc

Can anyone recommend a more logical and elegant way than this?

Answer

Your way looks clean for me except the fact that randomNumber > 0.87 is redundant.

if you store the value x, y and z in an array, you can probably write some cleaner code for example:

let prob = [100, 10, 5];
let sum = prob.reduce((a, b) => a + b, 0);
let normalizedProb = prob.map(p => p / sum);
let cummulativeProb = normalizedProb.map((cummulative => p => cummulative += p)(0));
for (let i = 0; i <= 50; i++) {
  let r = Math.random();
  console.log(cummulativeProb.filter(p => r >= p).length);
}

Also, you may want to read this post for faster implementation (in python though). However, the code will be more complicated for sure.