~/problems / Probability / Probability and expected value

Uniform 1..10 from a 1..7 die

medium ~20 min

You're given a function rand7() that returns a uniformly random integer in 1..7. Write

def rand10(rand7) -> int: ...

which returns a uniformly random integer in 1..10, using only rand7 as its source of randomness (no random module). Each of the ten values must come up with probability exactly 1/10.

Tempting but wrong: rand7() + rand7() - 4 clipped somehow, rand7() * rand7() % 10, or (rand7() + rand7()) % 10 + 1. Sums and products of dice are not uniform.

The tests call rand10 many times with a seeded rand7, check that each value's frequency is close to 10%, that the same rand7 stream always gives the same answers, and that you average fewer than 3 rand7 calls per result.

Hint: Keep x <= 40 and map it with (x - 1) % 10 + 1 (e.g. a = 3, b = 5 gives 19, so return 9); for x > 40, discard it and roll again. Only 9 of 49 outcomes are discarded, so you average under 2.5 calls.

Show hint

Two rolls a, b give (a - 1) * 7 + b, which is uniform over 1..49. You can't split 49 outcomes evenly into 10 groups, but you can split some of them evenly; what should happen with the rest?

Topic: Probability and expected value. Linearity of expectation, conditioning, Markov-chain equations; answers as fractions.

0:00
Ctrl ' run · Ctrl ↵ submit
esc