Pyth, 4 bytes
W
~O
Try it online!
This basically implements the algorithm:
\$ \begin{align} % Unknown environment algorithm :(
&Q \gets \text{input} \\
&\mathbf{Repeat} \\
&\begin{array}{cl}
1. & temp \gets Q \\
2. & Q \gets \text{unif}\{ 0, Q - 1 \} \\
3. & \mathtt{Print}(temp)
\end{array} \\
&\mathbf{Until} \quad temp = 0
\end{align} \$
To translate the Pyth into the algorithm, we can mostly just examine what each character means. Since Pyth is written in prefix notation (i.e. * + 1 2 3
is (1 + 2) * 3
) we can start from the left and fill in the arguments as we go.
W
begins a traditional while loop. The first statement after it is the loop condition and the second statement after it is the loop body. If the second statement is empty it becomes a no-op. This while works exactly like the Python while, so it will evaluate non-zero integers as True and zero as false.
The first statement after the while begins with the newline character. This corresponds to Pyth's "print and return with a newline" function. This takes one argument, which is then printed and also returned unmodified. This allows us to print the intermediate steps while also performing the needed operations.
The argument passed to this print function begins with ~
which is a bit special. If the character immediately after ~
is a variable it takes two arguments, otherwise it takes one. Since O
is not a variable ~
will consume only one argument. ~
functions a bit like +=
does in many conventional languages, though the closest operator would be the post-increment operator ++
from C
. You may know that x++
will be like using x
as the current value, but thereafter x
will be x+1
. ~
is the same idea, but generalised to whatever the result of the first argument is. How it picks what variable to assign to will be addressed later.
The argument of ~
is O
which is very simple. When its one argument is an integer O
returns a value from 0 to one less than that integer uniformly at random.
Now you may have noticed O
does not have an argument. Here the Pyth interpreter kindly fills in a guess, which here is the variable Q
. Q
has a special meaning in Pyth: whenever it is present in a program the Pyth program begins with assigning Q
to the input of the program. Since this is the first variable occurring in ~
's argument Q
is also now the variable that ~
will assign a value to.
Summed up our "readable" program might look like:
while print_and_return( assign_variable( Q, unif(0, Q-1) ) ):
pass
And one sample "run-through" might look like:
- Q = 5
O
returns 3, ~
returns 5, \n
returns and prints 5 which is true
- Q = 3
O
returns 0, ~
returns 3, \n
returns and prints 3 which is true
- Q=0
O
returns something irrelevant, ~
returns 0, \n
returns and prints 0 which is false
- Q = something irrelevant
- Terminate
If the submission is a function, may it return 0 in addition to printing it? – Adám – 2018-07-09T12:55:45.997
1@Adám yes, you can return in addition – Luis felipe De jesus Munoz – 2018-07-09T12:59:33.070
Do I need to seed my RNG? – SIGSTACKFAULT – 2018-07-09T16:16:41.110
May we print without delimiters? – Titus – 2018-07-30T15:44:28.760
I got curious. It's quite easy to prove that the average number of steps this program takes before it terminates is H(K-1) + 1 where H(K) is the K'th harmonic number. For n=1000, that's 8.484 steps on average.
– J.Doe – 2018-09-21T14:02:42.187