39
\$\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\$
18
  • 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 Jan 28 at 14:52
  • 2
    \$\begingroup\$ Surely if the integers must be chosen independently, then the output cannot be unique? \$\endgroup\$ – pxeger Jan 28 at 15:50
  • 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 Jan 28 at 16:06
  • 7
    \$\begingroup\$ @pxeger FWIW I agree with pxeger. The output numbers being unique is not compatible with independence \$\endgroup\$ – Luis Mendo Jan 28 at 16:15
  • 1
    \$\begingroup\$ @LuisMendo Yep, that’s fine \$\endgroup\$ – caird coinheringaahing Jan 28 at 16:40

69 Answers 69

1 2
3
2
\$\begingroup\$

Pxem, Filename: 23 17 bytes + Content: 0 bytes = 23 17 bytes, depends on ASCII-compatible encoding.

  • Filename: d.!.t.w.m.r.c.n,.o.a
  • Content: empty

Commented

d.t  # heap = 100
.w # loop
  .m.r # push(random(min=0,max=heap-1))
  .c # dup()
  .n # printf("%d",pop())
  ,.o # putchar(',')
.a # break if pop()==0
\$\endgroup\$
2
\$\begingroup\$

Vyxal, 6 bytes

{₁ʁ℅…|

Try it Online!

I'm actually quite happy with the way this one turned out. It's always fun when you can print things in the loop's condition.

Explained

{₁ʁ℅…|
{      # Open a while loop which loops while:
 ₁ʁ    #      From the range [0, 100)
   ℅   #      A randomly chosen item is truthy (non-0)
    …  #      (Print that value without popping it)
     | # Branch to the empty body of the while loop

In summary, this works by randomly choosing and printing a random number in the range [0, 100) until that value is 0.

\$\endgroup\$
1
\$\begingroup\$

Python 3.8 (pre-release), 51 bytes

from random import*
while n:=randint(0,99):print(n)

Try it online!

\$\endgroup\$
1
  • 6
    \$\begingroup\$ The challenge requires printing the final zero. \$\endgroup\$ – xnor Jan 29 at 0:36
1
\$\begingroup\$

Tcl, 54 bytes

while {[set R [expr int(rand()*99)]]} {puts $R}
puts 0

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Japt, 11 bytes

Lö
OpU
?ß:P

Try it online!

Outputs delimited by newlines, with a trailing newline after the 0

Lö      # Get a random number from [0...99] and store it as U
OpU     # Print U and a newline
?       # If U is non-zero:
 ß      #  Run the program again
  :P    # Otherwise end with no further output
\$\endgroup\$
1
\$\begingroup\$

><>, 50 bytes

701>x1>$:2*}*+ }1-:?!v}30.>
   ^\0/.;?=0oan:%*aar<

Try it online!

After many iterations, I got down to this version. Pretty happy with it, although I will admit I'm not convinced it's optimal.

Explanation

The ><> language doesn't have a natural builtin for generating a random number in a range. The only source of randomness we have is the x command, which sends the IP in a random direction. This gives us 1 of 4 options, which doesn't immediately fit into the range 0-99. However, we can easily use this command to generate a random bit, 0 or 1, like so:

>x1>
^\0/

Going in a left-to-right direction, the IP can either be sent leftwards back to the >, where it tries again, upwards, wrapping around to try again, rightwards to 1, or downwards to 0. This uniformly generates a random bit, although perhaps it can be made shorter by making that not so.

We're going to loop 7 times each time we generate a random number, for 7 bits. This will give us the binary for numbers from 0 to 127—more than we need, but we'll fix that later. Instead of collecting all the bits and subsequently converting that to a decimal number, we'll do both steps at once. 701 initializes the stack with our configuration. 7 is the loop count, 0 is the running sum, and 1 is the multiplicative factor.

$:2* will make a copy of the multiplicative factor and double that copy for the next iteration. }*+ will multiply the generated bit by the multiplicative factor and add it to the sum. }1-:?!v will decrement the loop counter, and if it's 0, stop looping. }30., in the event we don't stop, will reorganize the stack for the next iteration and jump back to the beginning (past the initialization).

The second line mostly contains the outer loop. It is written "backwards" to save space. First, r will place the generated sum on the top of the stack. %*aa will take that value mod 100, giving us a value from 0 to 99, albeit not uniformly. Then, we simply output that number followed by a newline (oan:). After that, ;?=0 terminates the program if 0.

We then have a single . command, which pops y and x off the stack and jumps to that location in the code. Since the stack contains [0, 64] at this point (the counter and the multiplicative factor, respectively), this jumps to (0, 64). Of course, this position doesn't exist in the code. In the Python implementation (the standard one), the interpreter will first increment this by the delta, which, at the time of execution, is (-1, 0). So, the IP is then (-1, 64) internally. To resolve this, ><> will first fix the y-coordinate, wrapping it around to 0 since it exceeds the bound, giving (-1, 0). When x < 0, it gets wrapped around to the end of the line, hopping to (28, 0), which is the > command. This puts us back on the right direction and back at the beginning of the line.

Catalogue of Attempts

103 bytes: My first attempt. Completely ungolfed. First collects the bits, then converts it to a decimal in a separate stage.

7>x1>$1-:?!v!
 ^\0^   v$1<
{2*$l2=?\@:}*+
  !     >:0=?v:'d'(?v     >0[700.
           ;n<      >n' 'o^

105 bytes: Post calculating the sum while collecting bits. Longer, but the structure offers us more opportunities to golf.

701>x1>$:}*+}1-:?!v}2*30.
   ^\0^           >r:0=?v:'d'(?v     >0[700.
                      ;n<      >n' 'o^

90 bytes: Introducing the modulus trick, rather than retrying if the number is 100 ('d') or more.

701>x1>$:}*+}1-:?!v}2*30.
   ^\0^           >r:0=?vaa*%nao0[700.
                      ;n<

64 bytes: Inlining the terminate-if-zero condition.

701>x1>$:}*+}1-:?!v}2*30.
   ^\0^           >raa*%:nao0=?;0[700.

54 bytes: Moving the modulo calculation into the main loop so we have enough room to flip the second line and tuck it into the whitespace we have.

701>x1>$:}*+aa*%}1-:?!v}2*30.>
   ^\0/     .;?=0oan:r<

53 bytes: Since we have spare whitespace left, we can use it to set the pointer in the right direction to save the > off the first line. Since that means we're jumping to the beginning of the line, we'd naturally skip 7, so we have to duplicate it before we jump.

701>x1>$:}*+aa*%}1-:?!v}2*30.
   ^\0/ #.!@7;?=0oan:r<

This approach, however, left me at a dead end, so I tried putting the modulo calculation back into the second part, which leaves us with what we currently have.

\$\endgroup\$
1
\$\begingroup\$

VBScript, 51 bytes

Randomize
Do
r=Int(100*Rnd)
msgbox r
Loop Until r=0
\$\endgroup\$
1
\$\begingroup\$

CSASM v2.2.1, 74 bytes

func main:
.lbl a
push 100
extern Random.Next(i32)
dup
print.n
brtrue a
ret
end

Commented:

func main:
    .lbl loop
        ; Get a random number in [0, 99]
        push 100
        extern Random.Next(i32)
        ; Duplicate it so it can be printed and then checked
        dup
        print.n
        ; Keep looping as long as the i32 generated is truthy (non-zero)
        brtrue loop
    ret
end
\$\endgroup\$
1
\$\begingroup\$

GolfScript, 14/15 bytes

{100rand.}do]`

Try it online!

Uses rand built-in to generate random numbers from 0-99, inside a do loop to terminate once a 0 is generated. The output of the loop is collected into an array and formatted for output. If the brackets and quotation marks invalidate the output, here is another version that sacrifices 1 byte for cleaner output:

{' '100rand.}do

Try it online!

\$\endgroup\$
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.