Nerdsniped!
Here's my solution:
v
v >2\ v
>>>::0\0\>:|:/2<>*\v v<<<<<<<
^ >$1\:| :<>:2v # ^ @
^ >$ :|:/< >>+>>v \ .
> #^?>\$>\:| -
>^ >$-:0`|
^ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $<
Enter on the left, with n
on the stack. Each |
marks a new phase of the algorithm.
- In the first phase, we initialize the stack with
n n 0 0 n
and transform that n
into 2 2 ... 2 2
.
- In the second phase, we multiply up all those 2s to yield
n n 0 0 2^k
for k >= lg n
.
- In the third phase, we transform
2^k
into m
= 2^k + 2^{k-1} + 2^{k-2} + ... + 4 + 2 + 1
, except that we use ?
to skip each term with 50% probability.
- In the final phase, we transform
n n m
into (if n > m
) m
, and print it; or (if n <= m
) n
, and return to the beginning of the entire algorithm.
This generates an unbiased uniform distribution in the half-open range [0..n)
, for any n
supplied by the caller.
Here's a test harness that generates and prints 52*:*
= 100 unbiased integers from the half-open range [0, 10'000)
. Run it on tio.run.
52*:* v
v***:::*52_@#:-1 < <
v
v >2\ v ^
>::0\0\>:|:/2<>*\v v<<<<<<< ^
^ >$1\:| :<>:2v # ^ ^
^ >$ :|:/< >>+>>v \ .
^ > #^?>\$>\:| -
^ >^ >$-:0`|
^ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $<