29
\$\begingroup\$

Challenge

I'm under attack by the larcenous Midnight Crew and I need to summon the Catenative Doomsday Dice Cascader in order to defend myself. Since I'm low on space, I need the code to be as short as possible.

The algorithm for the Catenative Doomsday Dice Cascader is as follows:

First, the six sided die in the Prime Bubble is rolled, and the result will determine how many iterations of the next step take place.

Start with a six sided die. For as many times as the roll of the Prime Bubble die, multiply the number of sides on the next die by the result of the roll of the current die. For example, if on your first roll of the six-sided die your roll is 2, then your next die will have 6*2 = 12 sides.

Your goal is to write a function or program that takes no input and outputs the final result of the last die rolled. Since this is , the lowest byte count in each language wins!

Examples

Example #1 (Taken directly from the link above):

The Prime Bubble rolls a 6, meaning that the Cascader will iterate six times

#1: We always start with a 6 sided die, and it rolls a 2, so the next die has 6x2=12 sides
#2: The 12 sided die rolls an 8, meaning that the third die has 12x8=96 sides
#3: The 96 sided die rolls a 35, meaning that die 4 has 96x35=3360 sides
#4: The 3360 sided die rolls a 2922, so die 5 has 3360x2922 = 9,817,920 sides
#5: The 9.8 million sided die rolls a 5,101,894, so the final die has 50,089,987,140,480 sides
#6: The 50 trillion sided die rolls a one. Hooray. 
Since the last die rolled gave a 1, your function or program should output 1.

Example #2

The Prime Bubble rolls a 2, meaning that the Cascader will iterate twice.

#1: We always start with a 6 sided die, and it rolls a 4, so the next die has 6x4 = 24 sides
#2: The 24 sided die rolls a 14

Since the last die rolled gave a 14, your function or program should output 14.
\$\endgroup\$
  • 4
    \$\begingroup\$ Whats the maximum output? If every roll results in the maximum side? I think it's 7958661109946400884391936 = ((((6^2)^2)^2)^2)^2 = 6^(2^5) = 6^32 \$\endgroup\$ – Kjetil S. Jun 1 at 11:53
  • 6
    \$\begingroup\$ @KjetilS. Indeed, and the likelihood of that output should be \$\frac{1}{6*\prod_{i=0}^5(6^{2^i})}=\frac{1}{6\times 6\times 6^2\times 6^4\times 6^8\times 6^{16}\times 6^{32}}=\frac{1}{2155416739906037495048372267884096782336}\$ \$\endgroup\$ – Jonathan Allan Jun 1 at 12:50
  • 3
    \$\begingroup\$ Is this supposed to be random? The question doesn't mention anything about randomness at all? \$\endgroup\$ – Sriotchilism O'Zaic Jun 1 at 16:35
  • 10
    \$\begingroup\$ @SriotchilismO'Zaic Dice-rolling implies randomness. \$\endgroup\$ – mbomb007 Jun 1 at 21:34
  • 6
    \$\begingroup\$ @SriotchilismO'Zaic xkcd.com/221 \$\endgroup\$ – Neyt Jun 3 at 9:52

20 Answers 20

8
\$\begingroup\$

Python 2, 76 69 bytes

from random import*
R=randint
v=6;exec"p=R(1,v);v*=p;"*R(1,6)
print p

Try it online!

\$\endgroup\$
8
\$\begingroup\$

Perl 6, 43 37 bytes

-6 bytes thanks to nwellnhof

{(6,{roll 1..[*] @_:}...*)[1+6.rand]}

Try it online!

Anonymous code block that returns the doomsday dice result.

Explanation:

{                                   }   # Anonymous code block
 (                       )[1+6.rand]    # Take a random number from
                     ...*               # The infinite list of
  6,{roll 1..[*] @_:}                   # Cascading dice values
  6,                                    # Starting from 6
    {roll          :}                   # And choosing a random value from
          1..                           # One to
             [*] @_                     # The product of every value so far
\$\endgroup\$
7
\$\begingroup\$

Wolfram Language (Mathematica), 43 bytes

(r=RandomInteger)@{1,Nest[r@{1,#}#&,6,r@5]}

Try it online!

\$\endgroup\$
5
\$\begingroup\$

J, 21 bytes

1+[:?(*1+?)^:(?`])@6x

Try it online!

+6 bytes thanks to a logic problem spotted by FrownyFrog

NOTE: J has no niladic verbs. However, this verb will work the same no matter what argument you give it. In the TIO example, I'm calling it with 0, but I could have used 99 or '' just as well.

how

  • 1+ add one to...
  • [:? a single roll of an n-sided die (sides reading 0 to n-1), where the number n is determined by...
  • (*1+?) take the current argument y and roll ? to produce a random number between 0 and y-1. 1+ makes that 1 to y, inclusive. Finally the * creates a J hook, which will multiply that by y again.
  • ^: do the above this many times...
  • (?`]) ? roll the initial argument, which is 6, to determine how many times to repeat. If we roll 0 (corresponding to a 1 on the Prime Bubble), the argument will pass through unchanged. The ] indicates that 6, unchanged, will be the starting value of repeated (*1+?) verb that determines the die value for the final roll.
  • @6x attaches the constant verb 6, so that we can call it with anything, and the x forces J to use extended integer computation which we need for the possibly huge numbers.
\$\endgroup\$
  • \$\begingroup\$ in this case 0 executes the previous verb once, 1 twice, etc why is that? \$\endgroup\$ – FrownyFrog Jun 1 at 23:15
  • \$\begingroup\$ because i made a mistake :(. will fix soon. \$\endgroup\$ – Jonah Jun 1 at 23:42
  • \$\begingroup\$ Fixed now. Thanks. \$\endgroup\$ – Jonah Jun 1 at 23:55
4
\$\begingroup\$

K (oK), 32 bytes

Solution:

*|{x,1+1?x:(*).x}/[*a;6,a:1+1?6]

Try it online!

Start with 6 and "1 choose 6", iterate over "1 choose 6" times:

*|{x,1+1?x:(*).x}/[*a;6,a:1+1?6] / the solution
  {             }/[n;    c     ] / iterate over lambda n times with starting condition c
                            1?6  / 1 choose 6, between 0..5 (returns a list of 1 item)
                          1+     / add 1 (so between 1..6)
                        a:       / store as 'a'
                      6,         / prepend 6, the number of sides of the first dice
                   *a            / we are iterating between 0 and 5 times, take first (*)
           (*).x                 / multi-argument apply (.) multiply (*) to x, e.g. 6*2 => 12
         x:                      / save that as 'x'
       1?                        / 1 choose x, between 0..x-1
     1+                          / add 1 (so between 1..x)
   x,                            / prepend x
*|                               / reverse-first aka 'last'

You can see the iterations by switching the over for a scan, e.g.

(6 3        / 1 choose 6 => 3, so perform 3 iterations
 18 15      / 1 choose (6*3=18) => 15
 270 31     / 1 choose (18*15=270) => 31
 8370 5280) / 1 choose (270*31=8730) => 5280
\$\endgroup\$
  • 1
    \$\begingroup\$ (*).x -> */x and { }/[*a;6,a:1+1?6] -> a{ }/6,a:*1+1?6 \$\endgroup\$ – ngn Jun 7 at 23:16
4
\$\begingroup\$

Jelly, 9 bytes

6X×$5СXX

A niladic Link which yields a positive integer.

Try it online!

Saving a byte over the more obvious 6X×$6X’¤¡X

How?

6X×$5СXX - Link: no arguments
6         - initialise left argument to 6
    5С   - repeat five times, collecting up as we go: -> a list of 6 possible dice sizes
   $      -   last two links as a monad = f(v):           e.g [6,18,288,4032,1382976,216315425088]
 X        -     random number in [1,v]                     or [6,6,6,6,6,6]
  ×       -     multiply (by v)                            or [6,36,1296,1679616,2821109907456,7958661109946400884391936]
       X  - random choice (since the input is now a list) -> faces (on final die)
        X - random number in [1,faces]
\$\endgroup\$
  • \$\begingroup\$ Nice. I was trying to think of a way from moving beyond my ‘obvious’ answer, but didn’t think of generating all the dice and then picking one at random. \$\endgroup\$ – Nick Kennedy Jun 1 at 13:50
  • \$\begingroup\$ Heh, I missed that you'd posted almost that exact answer! \$\endgroup\$ – Jonathan Allan Jun 1 at 14:01
3
\$\begingroup\$

05AB1E, 10 bytes

X6DLΩF*DLΩ

The random choice builtin for large lists is pretty slow, so may result in a timeout if the Prime Bubble roll is for example a 6.

Try it online or try it online with added prints to see the rolls. (TIO uses the legacy version of 05AB1E, since it's slightly faster.)

Explanation:

X           # Push a 1 to the stack
 6          # Push a 6 to the stack
  D         # Push another 6 to the stack
   L        # Pop the top 6, and push a list [1,2,3,4,5,6] to the stack
    Ω       # Pop and push a random item from this list (this is out Prime Bubble roll)
     F      # Loop that many times:
      *     #  Multiply the top two values on the stack
            #  (which is why we had the initial 1 and duplicated 6 before the loop)
       D    #  Duplicate this result
        LΩ  #  Pop and push a random value from its ranged list again
            # (after the loop, output the top of the stack implicitly)
\$\endgroup\$
3
\$\begingroup\$

Jelly, 9 bytes

6×X$X’$¡X

Try it online!

Jonathan Allan's answer claims that it's

Saving a byte over the more obvious 6X×$6X’¤¡X

. In fact, we don't need to make such a big modification. Therefore, this is an alternative approach to Jonathan Allan's answer, and, also, a resting place for my initial invalid 6-byter. :(

\$\endgroup\$
2
\$\begingroup\$

Perl 5, 54 bytes

$a=6;map$a*=$r=1+int rand$a,0..rand 6;say 1+int rand$r

Try it online!

\$\endgroup\$
  • \$\begingroup\$ That's one rand too many, you should just say$r \$\endgroup\$ – Grimy Jun 1 at 19:25
2
\$\begingroup\$

Charcoal, 16 bytes

⊞υ⁶F⊕‽⁶⊞υ⊕‽ΠυI⊟υ

Try it online! Link is to verbose version of code. Explanation:

⊞υ⁶

Push 6 to the predefined list.

F⊕‽⁶

Repeat a random number of times from 1 to 6...

⊞υ⊕‽Πυ

... push a random number between 1 and the product of the list to the list.

I⊟υ

Output the last number pushed to the list.

Alternative approach, also 16 bytes

≔⁶θF‽⁶≧×⊕‽θθI⊕‽θ

Try it online! Link is to verbose version of code. Explanation:

≔⁶θ

Set the number of sides to 6.

F‽⁶

Repeat a random number between 0 and 5 times...

≧×⊕‽θθ

... multiply the number of sides by a random number from 1 to the number of sides.

I⊕‽θ

Print a random number from 1 to the number of sides.

\$\endgroup\$
2
\$\begingroup\$

Python 3, 76 bytes

from random import*
r=randint
a=6
for i in" "*r(0,5):a*=r(1,a)
print(r(1,a))

Try it online!

-2 bytes thanks to TFeld

\$\endgroup\$
  • 1
    \$\begingroup\$ -2 bytes by changing the import \$\endgroup\$ – TFeld Jun 1 at 7:34
  • \$\begingroup\$ @TFeld thanks [filler] \$\endgroup\$ – HyperNeutrino Jun 1 at 19:23
2
\$\begingroup\$

R, 43 bytes

s=sample
for(i in 1:s(k<-6))T=s(k<-k*T,1)
T

Try it online!

k keeps track of the current number of faces on the die. Uses the fact that T is initialized as 1.

I tried a few other things, but couldn't beat this simple, straightforward approach.

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

Jelly, 10 bytes

6×X$6X’¤¡X

Try it online!

Explanation

       ¤   | Following as a nilad:
    6X     | - A random number between 1 and 6
      ’    | - Decrease by 1 (call this N)
6          | Now, start with 6
   $    ¡  | Repeat the following N times, as a monad
 ×         | - Multiply by:
  X        |   - A random number between 1 and the current total
         X | Finally, generate a random number between 1 and the output of the above loop
\$\endgroup\$
1
\$\begingroup\$

Ruby, 41 bytes

r=6;rand(2..7).times{r*=$s=rand 1..r};p$s

Try it online!

Explanation

r=6                                 # Set dice number to 6

rand(2..7).times{               }   # Repeat X times, where X=dice roll+1
                 r*=$s=rand 1..r    # Multiply dice number by a dice roll
                                    # Save the most recent dice roll

p$s                                 # Print last dice roll (this is why
                                    #  we did the last step one extra time)
\$\endgroup\$
1
\$\begingroup\$

Java 10, 214 93 86 bytes

v->{int r=6,n=0;for(var d=Math.random()*6;d-->0;n*=Math.random(),r*=++n)n=r;return n;}

Try it online or try it online with additional print-lines to see the steps.

-128 bytes by using int instead of java.math.BigInteger. \$6^{32}\$, the largest possible result, doesn't fit inside an int nor long, which is why BigInteger was used initially. OP allowed to use int and assuming it's infinitely large, so that saved more than 125 bytes here. :) (Here the previous 214 bytes version using BigIntegers.)

Explanation:

v->{                        // Method with empty unused parameter & integer return-type
  int r=6,                  //  The range in which to roll, starting at 6
      n=0;                  //  The roll itself (which must be initialized, therefor is 0)
  for(var d=Math.random()*6;//  Roll the Prime Bubble Dice
      d-->0                 //  Loop that many times:
      ;                     //    After every iteration:
       n*=Math.random(),    //     Roll a random dice in the range [0, n)
       r*=++n)              //     Increase `n` by 1 first with `++n`, so the range is [1,n]
                            //     And then multiply `r` by `n` for the new range
    n=r;                    //   Set `n` to `r`
  return n;}                //  After the loop, return `n` as result
\$\endgroup\$
  • \$\begingroup\$ Post the solution that doesn't do BigInteger as your competing solution. \$\endgroup\$ – Stackstuck Jun 3 at 16:16
  • \$\begingroup\$ @Stackstuck Will await what OP has to say to your comment. Was about to make one myself to confirm. I personally use BigIntegers/BigDecimals for challenges where it's necessary, unless OP explicitly states you can use your native max integer size (which is usually \$2^{32}\$, so int for both Java and .NET C#). \$\endgroup\$ – Kevin Cruijssen Jun 3 at 16:26
  • \$\begingroup\$ I'll see if I can find anything on meta about this. \$\endgroup\$ – Stackstuck Jun 3 at 16:29
  • 1
    \$\begingroup\$ OP says don't worry about integer size limits. Use the int type. \$\endgroup\$ – Stackstuck Jun 8 at 1:26
  • 1
    \$\begingroup\$ @Stackstuck Done, and golfed 7 bytes in the process. :) \$\endgroup\$ – Kevin Cruijssen Jun 8 at 12:00
0
\$\begingroup\$

PHP, 59 bytes

$r=$q=rand(1,$s=6);while($l++<$q)$r=rand(1,$s*=$r);print$r;

expanded:

$r=$q=rand(1,$s=6);
while($l++<$q)$ 
    r=rand(1,$s*=$r);
print$r;

Not sure if I'm supposed to include the open tag.

On my machine, it crashes if $s*$r is too large, so it doesn't print on $q>=5 sometimes... because the numbers get so big. Not sure of a fix.

\$\endgroup\$
0
\$\begingroup\$

Pyth, 14 bytes

uhO=*|Z6GO6hO6

Try it online!

uhO=*|Z6GO6hO6   
         O6      Random number in range [0-6)
u                Perform the following the above number of times...
           hO6   ... with starting value G a random number in range [1-6]:
    *   G          Multiply G with...
     |Z6           The value of Z, or 6 if it's the first time through (Z is 0 at program start)
   =  Z            Assign the above back into Z
  O                Random number in range [0-Z)
 h                 Increment
                 Implicit print result of final iteration
\$\endgroup\$
0
\$\begingroup\$

C# (.NET Core), 136 bytes

class A{static void Main(){var r=new System.Random();int i=r.Next(6),j=6;while(i-->0)j*=1+r.Next(j);System.Console.Write(r.Next(j)+1);}}

Try it online!

I'm pretty sure this works, given the assumption of infinite integer length that we're fond of here. If I have to actually handle the overflow, I'd need to bust out an entirely different class.

\$\endgroup\$
  • \$\begingroup\$ It can now give a System.ArgumentOutOfRangeException: 'maxValue' must be greater than zero error. The max result can be \$6^{32}\$, which is larger than the max size of both int and long, so you'll have to use BigIntegers instead. \$\endgroup\$ – Kevin Cruijssen Jun 3 at 9:34
  • \$\begingroup\$ @KevinCruijssen yes, that's the whole point of my comment. \$\endgroup\$ – Stackstuck Jun 3 at 16:12
0
\$\begingroup\$

Julia 1.0, 60 bytes

g(b=big(6),r=rand)=(for i in 1:r(0:5) b=b*r(1:b) end;r(1:b))

b=big(6) makes it work with arbitrary sized integers Try it online!

\$\endgroup\$
0
\$\begingroup\$

Gaia, 13 bytes

:(ṛ×
6₅ṛ(↑ₓ(ṛ

Try it online!

\$\endgroup\$

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.