Given I have a fair $n \in \mathbb{N}$-sided dice, and I want to generate an integer in the range of $[0, r), r \in \mathbb{N}$ with the same probability. I may roll the dice any number of times and stop anytime after observing the results. What is the best way to do this so that I do the least amount of expected dice rolls?
Intuitively, we can do it greedily so that anytime the number of possible outcomes is more than $r$, we take those outcomes out and re-roll when the rejection happens. In code, those will be something like (in the code, the dice numbers are zero-indexed):
def dice_rand(r, n):
cur_val = 0
max_val = 1
while True:
cur_val = n * cur_val + roll_dice(n)
max_val = n * max_val
d = floor(max_val / r)
if cur_val < d * r:
return floor(cur_val / d)
cur_val = cur_val - d * r
max_val = max_val - d * r
Now I have problem figuring out the expected dice rolls number for above algorithm. Also how do I prove the above algorithm is the most efficient?