In this problem you will need to keep a few dummy outputs (rejection sampling, as @Gene pointed out) on which you repeat the experiment performed.
I have provided two implementations here. The first one is sub-optimal, but easier to understand. The second one is more optimal but a little more difficult. Finally, I've tried to outline a proof and linked to a Math StackExchange answer.
First Approach -
Step 1 - Run rand1()
x + 1
times.
Step 2 - Check if the output is one-hot. By one-hot I mean, only 1 of the x + 1
runs results in 1
and all the others 0
. If not so, repeat Step 1. Else go to Step 3.
Step 3 - Print index of 1 as your output.
The python code will look like this -
def randx(x):
choice = -1
while choice == -1:
for i in range(0, x+1):
c = rand1()
if c == 1 and choice == -1:
choice = i
elif c == 1 and choice != -1:
choice = -1
break
Second Approach -
Of course, the first method is sub-optimal. You can make this far better, but it will need a lot more code. Let's say we want to do a prediction between x+1
values (0
to x
). You will need to carry out the experiment atleast k = ceil(log(x+1))
times. Now, each of the outcomes will have an equal probability of 1 / 2^k
.
Out of these 2^k
possibilities, assign some to numbers (due to our choice of k
, you will see that you can assign a number to atleast half the possibilities). Call the other possibilities dummy output.
When you get a dummy output, you simply repeat the experiment. If you don't, you output the number corresponding to that output.
As an example, if x = 4, x + 1 = 5. Hence we need k = 3
. Assign 0, 1, 2, 3, 4 their binary representations (000 to 101) and leave the remaining 3 as dummies. The pseudo code will look like this,
function randx(x):
choice = -1
runs = ceil(log(x+1))
while choice == -1:
output = 0
for i in range(0, runs):
output += pow(2, i)*rand1()
if output <= x:
choice = output
Why does this work?
We are giving all numbers equal probable events. If none of those events happen, we are simply repeating this experiment. If you look at the total probability of getting a number i
,
Let p = 1 / 2^k
Let q = 1 - (x+1)*p
Total probability of getting i = p + q*p + q*q*p + q*q*q*p ...
= p/(1-q)
= 1/(x+1)
Hence this sums up to 1 / (x+1).
For a more complete explanation with MathJax, refer to https://math.stackexchange.com/questions/2356/is-it-possible-to-split-coin-flipping-3-ways