25
\$\begingroup\$

You are to write a program which generates random integers between \$0\$ and \$99\$ inclusive, outputting each integer in turn, until \$0\$ is generated. You may choose which single-order random distribution (uniform, binomial, Poisson etc.) you use so long as each integer has a non-zero chance of being generated and is chosen independently. The output should always end with 0. As each integer must be chosen independently, the output cannot be some permutation of the integers \$\{0, 1, 2, ..., 99\}\$ trimmed to end with \$0\$.

You may follow another method to accomplish the same task, so long as the result is identical to the described method here (for example: you may generate a number \$K\$ geometrically distributed with parameter \$\frac 1 {99}\$, then output \$K\$ independent numbers with a uniform distribution on the set \$\{1, 2, ..., 99\}\$, then output a \$0\$).

The integers may be separated by any non-digit, non-empty separator (e.g. newlines, spaces etc.), and may be output in any consistent base. You may output in any convenient method or format.

This is so the shortest code in bytes wins.

\$\endgroup\$
  • 1
    \$\begingroup\$ @KevinCruijssen No, the integers do not have to be unique (aside from 0, which should appear exactly once), and yes, you may output them as a list \$\endgroup\$ – caird coinheringaahing yesterday
  • 2
    \$\begingroup\$ Surely if the integers must be chosen independently, then the output cannot be unique? \$\endgroup\$ – pxeger yesterday
  • 4
    \$\begingroup\$ @cairdcoinheringaahing for example, if a 5 is chosen, the chance of choosing another 5 has changed to 0. That isn't independent. \$\endgroup\$ – pxeger yesterday
  • 4
    \$\begingroup\$ @pxeger FWIW I agree with pxeger. The output numbers being unique is not compatible with independence \$\endgroup\$ – Luis Mendo yesterday
  • 1
    \$\begingroup\$ @LuisMendo Yep, that’s fine \$\endgroup\$ – caird coinheringaahing yesterday

49 Answers 49

12
\$\begingroup\$

R, 25 bytes

c(sample(99,rexp(1),T),0)

Try it online!

p(0) at each iteration is (e-1)/e.
p(each other number) at each iteration is (1/e)*(1/99).

Obviously this choice of random distribution gives a rather unsatisfying-looking output (since most of the runs are rather short). So this link uses the same approach, but changes p(0) to roughly 0.01 to illustrate some longer runs...

What's going on?

            rexp(1)         # First determine where the '0' will occur:
                            # We generate a single random number using
                            # an exponential distribution with a
                            # rate parameter equal to 1
                            # (so the chance of any value x is e^-x).  
c(                    ,0)   # Now place '0' at the subsequent position, 
  sample(99,rexp(1),T)      # and fill all the previous positions with
                            # numbers sampled from 1 to 99,
                            # with replacement (specified by the 'T' for TRUE).  
\$\endgroup\$
  • 1
    \$\begingroup\$ I see, you need the replace=T since there's a nonzero probability that the sample size will be larger than 99, though in practice, it seems...unlikely. exp(-100) or so? \$\endgroup\$ – Giuseppe 21 hours ago
  • \$\begingroup\$ @Giuseppe - Yup. Also, the output needs to be the same as independent sampling, so this would be violated without replacement. \$\endgroup\$ – Dominic van Essen 21 hours ago
8
\$\begingroup\$

Random Brainfuck, 67 66 65 bytes

>>+[-<?>>-[<++>-----]<--<[>->+<[>]>[<+>-]<<[<]>-]>[-]>.[<+>[-]]<]

Try it online!

Finally found a use for this silly variant.

Assumes wrapping cells.

Basically, Random Brainfuck is just normal Brainfuck, except it adds the ? opcode which reads a byte from /dev/urandom.

All I have to do is modulo 100.

Outputs random bytes to stdout.

>>+                           0 0 (1)  0
[ do
    -                         0 0 (0) 0
    <?>>                      0 rnd (0) 0
    -[<++>-----]<--           0 rnd (100) 0
    <[>->+<[>]>[<+>-]<<[<]>-] 0 (0) * rnd%100
    >[-]>                     0 0 false (rnd%100) 
    .                         print
    [ if rnd%100 is nonzero was_nonzero = true
      <+>                     0 0 true (0)
    [-]]
    <                         0 0 (was_nonzero) 0
] while was_nonzero

The equivalent C algorithm:

void print_random(void)
{
    bool was_nonzero;
    do {
        uint8_t rng = randbyte() % 100;
        was_nonzero = rng != 0;
        putchar(rng);
        rng = randbyte();
    } while (was_nonzero);
}
\$\endgroup\$
7
\$\begingroup\$

Python 3, 58 bytes

from random import*
print(*iter(lambda:randint(0,99),0),0)

Try it online!

\$\endgroup\$
7
\$\begingroup\$

Scratch 3.0, 9 blocks/76 bytes

beautiful

As SB Syntax:

define
set[N v]to(1
repeat until<(N)=(0
set[N v]to(pick random(0)to(99
say(N

Try it on Scratch

It just wouldn't be right if I didn't golf this in scratch. This is a function that achieves the desired result

Explained

define                             // Create a function with no name (not a lambda)
set[N v]to(1                       // Initalise the variable we will use to generate random numbers with
                                   // If we didn't set it to 1, the next loop wouldn't start, as it would see that N = 0.
repeat until<(N)=(0                // Pretty self-explanatory
set[N v]to(pick random(0)to(99     // Also pretty self-explanatory. But putting this here means we don't have to include two calls to this block: we've essentially created a post-test loop instead of a pre-test loop
say(N                              // Output the randomly generated number and repeat
\$\endgroup\$
7
\$\begingroup\$

R, 30 29 bytes

while(print(sample(0:99,1)))T

Try it online!

print returns its argument invisibly, so this will choose an integer from 0-99 uniformly at random until a 0 is printed, because 0 is falsey in R.

Uses the "do-while" tip.

Thanks to Robin Ryder for saving a byte.

\$\endgroup\$
6
\$\begingroup\$

Ruby, 19 18 bytes

-1 byte thanks to Dingus!

loop{1/p(rand~99)}

Try it online!

rand~99 generates a random integer below abs(~99)=abs(-100)=100, p prints it to the output and returns the integer as a function and 1/x fails for x==0, stopping the program.

\$\endgroup\$
  • \$\begingroup\$ @Dingus thats non-intuitive behaviour, thank you ;) \$\endgroup\$ – ovs 19 hours ago
  • \$\begingroup\$ Yes, I can't imagine the intended use case for negative arguments. Now a tip. \$\endgroup\$ – Dingus 16 hours ago