Implement Homestuck's Catenative Doomsday Dice Cascader

29

3

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.

Bazinga_9000

Posted 2019-06-01T02:48:59.320

Reputation: 807

4Whats 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 – Kjetil S. – 2019-06-01T11:53:49.497

6@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}$ – Jonathan Allan – 2019-06-01T12:50:01.870

3Is this supposed to be random? The question doesn't mention anything about randomness at all? – Post Rock Garf Hunter – 2019-06-01T16:35:50.463

10@SriotchilismO'Zaic Dice-rolling implies randomness. – mbomb007 – 2019-06-01T21:34:24.750

1Numbers are really huge this time — 6³² > 2⁶⁴ obviously. – val says Reinstate Monica – 2019-06-02T16:27:09.910

2Does the roll of a 1 on the Prime Bubble mean you immediately roll the Final Die? – Stackstuck – 2019-06-02T19:52:42.363

1@Stackstuck yes, and it’s just a 6-sided one – Nick Kennedy – 2019-06-02T22:40:31.127

6

@SriotchilismO'Zaic https://xkcd.com/221/

– Neyt – 2019-06-03T09:52:15.193

2To confirm: We don't need to worry about type size limits, right? – Stackstuck – 2019-06-03T16:20:34.630

It's interesting not seeing a JavaScript answer, when current implementations have a BigNum type built in. – trlkly – 2019-06-04T08:32:41.393

2@Stackstuck you don't have to worry about integer size limits. Just pretend that int is infinitely large – Bazinga_9000 – 2019-06-04T20:57:31.270

@KevinCruijssen That settles that question, then. – Stackstuck – 2019-06-04T22:17:11.937

Answers

8

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!

Chas Brown

Posted 2019-06-01T02:48:59.320

Reputation: 8 959

8

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

Jo King

Posted 2019-06-01T02:48:59.320

Reputation: 38 234

7

Wolfram Language (Mathematica), 43 bytes

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

Try it online!

attinat

Posted 2019-06-01T02:48:59.320

Reputation: 3 495

5

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.

Jonah

Posted 2019-06-01T02:48:59.320

Reputation: 8 729

in this case 0 executes the previous verb once, 1 twice, etc why is that? – FrownyFrog – 2019-06-01T23:15:21.193

because i made a mistake :(. will fix soon. – Jonah – 2019-06-01T23:42:09.623

Fixed now. Thanks. – Jonah – 2019-06-01T23:55:30.293

4

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

streetster

Posted 2019-06-01T02:48:59.320

Reputation: 3 635

1(*).x -> */x and { }/[*a;6,a:1+1?6] -> a{ }/6,a:*1+1?6 – ngn – 2019-06-07T23:16:16.793

4

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]

Jonathan Allan

Posted 2019-06-01T02:48:59.320

Reputation: 67 804

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. – Nick Kennedy – 2019-06-01T13:50:07.167

Heh, I missed that you'd posted almost that exact answer! – Jonathan Allan – 2019-06-01T14:01:26.777

3

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)

Kevin Cruijssen

Posted 2019-06-01T02:48:59.320

Reputation: 67 575

3

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. :(

Erik the Outgolfer

Posted 2019-06-01T02:48:59.320

Reputation: 38 134

2

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

HyperNeutrino

Posted 2019-06-01T02:48:59.320

Reputation: 26 575

1-2 bytes by changing the import – TFeld – 2019-06-01T07:34:35.957

@TFeld thanks [filler] – HyperNeutrino – 2019-06-01T19:23:35.677

2

Perl 5, 54 bytes

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

Try it online!

Xcali

Posted 2019-06-01T02:48:59.320

Reputation: 7 671

That's one rand too many, you should just say$r – Grimmy – 2019-06-01T19:25:18.910

2

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.

Neil

Posted 2019-06-01T02:48:59.320

Reputation: 95 035

2

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.

Robin Ryder

Posted 2019-06-01T02:48:59.320

Reputation: 6 625

1

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

Nick Kennedy

Posted 2019-06-01T02:48:59.320

Reputation: 11 829

1

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

Kevin Cruijssen

Posted 2019-06-01T02:48:59.320

Reputation: 67 575

Post the solution that doesn't do BigInteger as your competing solution. – Stackstuck – 2019-06-03T16:16:44.937

@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#). – Kevin Cruijssen – 2019-06-03T16:26:30.220

I'll see if I can find anything on meta about this. – Stackstuck – 2019-06-03T16:29:52.243

1OP says don't worry about integer size limits. Use the int type. – Stackstuck – 2019-06-08T01:26:33.237

1@Stackstuck Done, and golfed 7 bytes in the process. :) – Kevin Cruijssen – 2019-06-08T12:00:24.357

1

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)

Value Ink

Posted 2019-06-01T02:48:59.320

Reputation: 10 608

0

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.

Reed

Posted 2019-06-01T02:48:59.320

Reputation: 141

0

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.

Stackstuck

Posted 2019-06-01T02:48:59.320

Reputation: 209

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. – Kevin Cruijssen – 2019-06-03T09:34:37.860

@KevinCruijssen yes, that's the whole point of my comment. – Stackstuck – 2019-06-03T16:12:24.993

0

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

Sok

Posted 2019-06-01T02:48:59.320

Reputation: 5 592

0

Gaia, 13 bytes

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

Try it online!

Giuseppe

Posted 2019-06-01T02:48:59.320

Reputation: 21 077

0

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!

gggg

Posted 2019-06-01T02:48:59.320

Reputation: 1 715