Generating a random number in Befunge

315 Views Asked by At

I want to generate a random number in Befunge, from 0 to n, where n is an arbitrary number. How would I go about doing this?
I thought of trying this (this example has 2 chained chunks of code to show how it works):

v  v
?#>?#>
1  1
+  +
> ^> ^

and repeating as needed, but I would need n copies of that chunk of code. Is there a better way I can generate a random number like rand(0, 10) in other languages?

3

There are 3 best solutions below

0
On

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`|
^ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $<
1
On

Shorter versions of MegaTom's solutions, taking advantage of wrapping:

0v     \_$
\?1+\1-:^:-1

TryItOnline!

and

0v   *2\_$
\?1+\1-:^:-1

TryItOnline!

Also, here's a very bouncy one-liner for the flat distribution (still wraps vertically at the ?), because why not! :)

1+01->1# +# #?\# 1# -# :#* #2 #\_$

TryItOnline!

1
On

This snippet will mostly do what you want. (It brakes on 0.)

0v    \<
>?>\1-:|
 1+    >$
 >^

Note that in both my generator and yours the distribution is not flat; it is binomial. This block will make a random number with a smooth distribution from 0 to 2^n-1:

0v  *2\<
>?>\1-:|
 1+    >$
 >^