This puzzle was told to me by a Stanford PhD student in a graduate course on randomized algorithms. It's really clever/beautiful, and I think makes for a great challenge.
You are given a fair coin, and your goal is to simulate a biased coin with an arbitrary(!) bias. On average, your method must terminate in 2 coin flips. You can have any probability p, p=1/pi, p=1/17, p=.25, etc.
To make this a bit more formal, I'll give some pseudo-code.
# flip() -> returns true with probably 1/2
# flip() is the only source of randomness allowed.
def biased_flip(p):
"""
Returns true with probability p.
"""
... # TODO: implement me!
if we call biased_flip() a million times, we will
expect flip() to have been called on average 2 million times
Any individual call could flip more than twice, but expectation is 2 per call.
for i in range(10e6):
biased_flip(random.uniform())
I promise it's possible.
Hint 1:
The solution begins with turning the probability p into a binary decimal string. For example, 1/4=0.01.
Hint 2:
k coin flips can be turned into a binary decimal, which will partition the interval [0, 1] into 2^k subintervals. Each of these subintervals are equally likely. As k approaches infinity, are able to sample essentially uniformly from [0, 1].
Hint 3:
Keep flipping the coin, and with each flip, build up a binary string. 1 if the flips is H, 0 if T. The flips HHTT -> 0.1100. If your binary string is below the expansion of p so far, will it ever go above? If it's above, will it ever go below?
Hint 4:
1 + 1/2 + 1/4 + 1/8 + 1/16 converges to 2.