The insight you need is that your bin()
function returns a single binary digit, or "bit". Invoking it once gives you 0 or 1. If you invoke it twice you get two bits b0
and b1
which can be combined as b1 * 2 + b0
, giving you one of 0, 1, 2 or 3 with equal probability. If you invoke it thrice you get three bits b0
, b1
and b2
. Put them together and you get b2 * 2^2 + b1 * 2 + b0
, giving you a member of {0, 1, 2, 3, 4, 5, 6, 7} with equal probability. And so on, as many as you want.
Your range [a, b] has m = b-a+1
values. You just need enough bits to generate a number between 0 and 2^n-1
, where n
is the smallest value that makes 2^n-1
greater than or equal to m
. Then just scale that set to start at a
and you're good.
So let's say you are given the range [20, 30]. There are 11 numbers there from 20 to 30 inclusive. 11 is greater than 8 (2^3), but less than 16 (2^4), so you'll need 4 bits. Use bin()
to generate four bits b0
, b1
, b2
, and b3
. Put them together as x = b3 * 2^3 + b2 * 2^2 + b1 * 2 + b0
. You'll get a result, x
, between 0 and 15. If x > 11 then generate another four bits. When x <= 11, your answer is x + 20
.