You are given a function foo() that represents a biased coin. When foo() is called, it returns 0 with 60% probability, and 1 with 40% probability. Write a new function that returns 0 and 1 with 50% probability each. Your function should use only foo(), no other library method.

You can easily find the solution in the link above, but I thought it in the wrong way: my first attempt was to return 0 if two tosses return (1,0) and (0,1), 1 otherwise. Apparently the math does not add up here: `P(1,0) + P(0,1) = 0.52`. Later I learned that John von Neumann has proposed an elegant algorithm to solve it (though not 100% efficient). Naturally, I asked myself: can I use the same unfair coin to generate 1, 2 and 3 with equal probability (i.e. each with chance 1/3)?

... I took the wrong path again. Trying to group all combinations by tossing the coin 3 times into 3 groups: (000, 111) -> discard & continue to toss; {1 one, 2 zeros} and {2 ones, 1 zero}. Unfortunately `P(1 one, 2 zeros) != P(2 ones, 1 zero)` plus I can't get 3 numbers out of this grouping mechanism. Someone on Twitter proposed the following:

Generate 3 bits. Return 0 if 100/011, 1 if 010/101, 2 if 001/110, start over if 000/111.

Inspired by the 3 case, I think the following should work if I were to use the same coin to generate 1-5 with equal probabilities:

Generate 5 bits. There will be 2^5 = 32 combinations in total. Occurrences of {1 one, 4 zeros} = {4 ones, 1 zero} = 5, whereas {2 ones, 3 zeros} = {3 ones, 2 zeros} = 10. Return each number by exhausting the following sequence: (1 combination from {1 one, 4 zeros} , 1 combination from {4 ones, 1 zero}, 2 combinations from {2 ones, 3 zeros}, 2 combinations from {3 ones, 2 zeros}). Repeat the process if either {00000, 11111} is obtained.

Note: the above process could be generalized to other prime, odd numbers. Non-prime odd numbers fail as there exists an odd number `d`, `2k < d` such that `d` cannot divide `C(d, 2k)` without a remainder. E.g. `d=9, k=3`.

It's entertaining to think through this kind of probability questions sometimes. Happy weekend!