Simulate a roll of a fair die, and output the result in this ascii-art form:
.-----------.
/ o o /|
/ /o|
/ o o / |
:-----------:o o|
| o o | |
| |o o:
| o | /
| |o/
| o o |/
'-----------'
Details
The outline of the die (i.e. the non-o characters) should be exactly as shown (with this orientation). The three faces should show the pip-patterns resulting from a random roll, in the manner shown.
You must simulate one fixed physical die. It must have faces 1...6 with opposite faces summing to 7.
You can choose whether the arrangement is left or right handed (i.e. whether 1-2-3 go clockwise or anticlockwise around their corner), and you can choose the orientations of the 2, 3 and 6 pip-patterns on their faces. For example, you might choose that the 6 face has its two lines of three pips next to the 3 and 4 faces. However, once these choices are made they must be used consistently, in the sense that the physical die cannot change its makeup. It just rotates randomly.
Thus, once the above choices are made, there should be exactly 24 possible outputs (8 choices for the sticking out corner * 3 rotations), and the program should output one of them chosen uniformly at random (as approximated by any reasonable PRNG).
The pip-patterns are as follows (with - for spaces for clarity). Each should be transformed by the appropriate affine map to fit on the face as in the example above.
--- --- o-- o-o o-o ooo
-o- o-o -o- --- -o- ---
--- --- --o o-o o-o ooo
Note: As has been pointed out, this choice of 2-pip pattern might be less common in real dice, but in the interests of fairness I'll insist on sticking to these patterns.
To make it completely explicit, each number's pips are a subset of
ooo
ooo
ooo
and here is what the die would look like with all 9 pips on every face:
.-----------.
/ o o o /|
/ o o o /o|
/ o o o /o |
:-----------:o o|
| o o o | o |
| |o o:
| o o o | o/
| |o/
| o o o |/
'-----------'
The output can be printed, or output as a string with newlines or a sequence of lines. Trailing spaces and up to one trailing blank line are allowed.
This is code-golf so shortest program in each language wins.
-
22\$\begingroup\$ I don't think I've ever seen a die where the 2 looks like that and not diagonal, interesting \$\endgroup\$RubenVerg– RubenVerg2024年10月13日 21:00:04 +00:00Commented Oct 13, 2024 at 21:00
-
\$\begingroup\$ To clarify what the appropriate affine map is/in the name of self-containedness, could you also provide an example cube where all faces show, say, the 3 pattern superimposed on the bottom half of the 6 pattern? \$\endgroup\$Unrelated String– Unrelated String2024年10月13日 21:02:34 +00:00Commented Oct 13, 2024 at 21:02
-
1\$\begingroup\$ @Unrelated String Fair point - I've added an all-9s picture \$\endgroup\$aeh5040– aeh50402024年10月13日 21:08:51 +00:00Commented Oct 13, 2024 at 21:08
-
2\$\begingroup\$ @RubenVerg Good catch. I wish I had noticed that weird "2" (or your comment) before writing my answer. :-/ \$\endgroup\$Arnauld– Arnauld2024年10月14日 01:58:42 +00:00Commented Oct 14, 2024 at 1:58
-
2\$\begingroup\$ Is this intended to prohibit languages with no source of randomness? May we accept an input to determine the orientation instead? \$\endgroup\$Toby Speight– Toby Speight2024年10月14日 14:54:28 +00:00Commented Oct 14, 2024 at 14:54
5 Answers 5
Python 3.8 (pre-release), (削除) 538 (削除ここまで) (削除) 478 (削除ここまで) (削除) 459 (削除ここまで) (削除) 441 (削除ここまで) (削除) 440 (削除ここまで) 438 bytes
-60 bytes by compressing some strings of characters in the die string.
-18 bytes by emanresu A.
-1 more byte by reducing 2*(c>3) to c//4*2.
-18 bytes by using not-quite-bytestrings-but-close-enough.
-1 byte by eliminating the need for the %12.
-2 bytes by using actual bytestrings and reemploying the %12.
from random import*
R=randrange
S=str.replace
P=lambda s:f'{ord("(TŅŕŭđŅŕLJ"[n[s]%12]):09b}'.translate(' o'*50)
c=R(8)
n=[3,*b''[c%4:][:2],2+c%2*6][::1-c//4*2]
for _ in[0]*R(3):n[1:]=[n[3]+6,n[1]+6,n[2]]
print(((S(S(S(""" .B.
/A/|
/A/}{|
/A/}{ |
:B:}{ }{|
|A| }{ |
C }{:
|A| }{/
C/
|A|/
'B'""",'A',' %s %s %s '),'B','-'*11),'C','|'+' '*11+'|}{')%(*P(3)+P(1),))[::-1].format(*(a:=P(2))[6:]+a[3:6]+a[:3]))[::-1])
I've been banging my head against this problem for about 2 hours now (new record!). Thankfully, the byte count has gone down 100 bytes from the original submission.
...Is that a good thing?
-
1\$\begingroup\$ 460 with some rearrangements \$\endgroup\$emanresu A– emanresu A2024年10月13日 23:34:39 +00:00Commented Oct 13, 2024 at 23:34
Charcoal, (削除) 146 (削除ここまで) 144 bytes
×ばつ‽40342156UMυE3⮌⭆§υ§ιλ§ξμ11P↗4↓:↓5↗'↗3↑:↑5←.←11↙.↙3↓:↓5:11J2±1F§υ0«P↗ιM4→»J1¦1E§υ2⟦⪫ι ⟧J14±2F§υ4«P↓⪫ι ↙
Try it online! Link is to verbose version of code. Explanation:
≔⪪⪪"..."3¦3υ
Split a compressed string into six die faces.
×ばつ‽40342156
Create a series of permutations, consisting of a 1⁄2 chance of rotating the die so that the 123 and 546 faces switch places (this is equivalent to three 90° rotations), a 1⁄3 chance each of rotating the die around the 123-456 long axis by multiples of 120° (which is achieved by repeating a permutation to make the face rotations cancel out), and a 1⁄4 chance each of rotating the die around the top-bottom axis by multiples of 90° (the top and bottom faces also have to be rotated in place, of course). For each permutation...
UMυE3⮌⭆§υ§ιλ§ξμ
... apply the permutation, rotating each face for each permutation.
11P↗4↓:↓5↗'↗3↑:↑5←.←11↙.↙3↓:↓5:11
Draw the outline of the die.
J2±1F§υ0«P↗ιM4→»
Draw the top face.
J1¦1E§υ2⟦⪫ι ⟧
Draw the front face.
J14±2F§υ4«P↓⪫ι ↙
Draw the right-hand face.
JavaScript (Node.js),(削除) 315 (削除ここまで)262 bytes
_=>`G .0.
G/1 3 2/|
/F 4 F/c|
/2 3 1/d |
:0:b a|
|7 5 6|E|
|GGG |a b:
|8 9 8| d/
|GGG |c/
|6 5 7|/
'0'`.replace(/\w/g,c=>c<1?'-----------':(u=c<{}?' ':'')+' o'[1&R>>('0xf'+c-5*e)%15]+u,R=[8724,18966,6864,1232,7218,6414,14998,6390][e=Math.random()*24|0,e%8])
Assume Arnauld's solution is correct as I geneated using its output
-
1\$\begingroup\$ @JonathanAllan Cuzof table need be even. Should get fixed \$\endgroup\$l4m2– l4m22024年10月14日 20:11:20 +00:00Commented Oct 14, 2024 at 20:11
05AB1E, 165 bytes
•1p61⁄4ujθ2
Ƶ@TV"α1⁄2[ÿTMÆÅ ́?μ1⁄4...ǝÆ2. ̃ãTMĀ"ê7‰Ć21ƵcÕ н5Å5ð ̈ôÚ•" ×ばつ:Ž£F0š0δšTΩiR}3LΩFÀÀ}4LΩFDŽBñS©èÁ®ǝεć4LNå+š]ε`•ʒ\RN]–ä•„o Åв3ô3ôsèsFøí]Ƶ2S©è€ ̃®s.;
Inspired by @Neil's Charcoal answer, so make sure to upvote that answer as well!
Explanation:
Step 1: Create the ASCII-art die, with placeholders for the nine positions of the random values:
•1p61⁄4ujθ2\nƵ@TV"α1⁄2[ÿTMÆÅ ́?μ1⁄4...ǝÆ2. ̃ãTMĀ"ê7‰Ć21ƵcÕ н5Å5ð ̈ôÚ•
"# Push compressed integer 165694505690730716563168121971474439450718220748920420519623075258410088668853618104539042325788146223319708232484170071664982
" 4|\n130/:2'."Åв # Convert the large integer to base-" 4|\n130/:2'.",
# aka, convert it to base-12, and index into this string
J # Join all characters togethe×ばつ: '# Replace all "2"s with a string consisting of 11 "-"s×ばつ: # Replace all "4"s with a string consisting of 3 spaces
Step 2a: Create the default representation of the die:
Ž£F # Push compressed integer 41325
0š # Convert it to a list of digits, and prepend a 0
δ # Map over each digit:
0 š # Pair it with a leading 0
The leading 0s are the rotation-state, indicating how many times we'll have to rotate the face in step 3. The values [0,5] are the indices of the die-faces [1,6].
Step 2b,c,d: Just like @Neil's Charcoal answer, \$\frac{1}{2}\$ chance of inverting the die (aka reversing the representation of the die); then \$\frac{1}{3}\$ chance of rotating the die 120 degrees around a corner (aka rotating the representation of the dice twice counterclockwise); and then \$\frac{1}{4}\$ chance of rotating the die 90 degrees around a face (aka rotating the representation of the die at the 0-based indices 3→0→4→5→3, and simultaneously increasing the rotation-state at the 0-based indices 1,2,3,4 each once clockwise):
T # Push 10
Ω # Pop and push a random digit of it
i # If it's 1:
R # Reverse the list
} # Close the if-statement
3L # Push list [1,2,3]
Ω # Pop and push a random digit of it
F # Loop that many times:
ÀÀ # Rotate the list twice counter-clockwise
} # Close the loop
4LΩF # Similar again, looping randomly [1,2,3,4] amount of times:
D # Duplicate the current list
ŽBñ # Push compressed integer 3045
S # Convert it to a list of digits: [3,0,4,5]
© # Store it in variable `®` (without popping)
è # Get the current value-states at those 0-based indices
Á # Rotate them once clockwise
® # Push indices [3,0,4,5] again
ǝ # Insert the rotated value-states back into the list at those indices
ε # Map over each value-state pair:
ć # Extract head (the current rotation-state)
4L # Push list [1,2,3,4]
Nå # Check if the current 0-based map-index is in this list
# (1 if the index is 1/2/3/4; 0 if the index is 0/5)
+ # Add that check to the rotation-state
š # And prepend it back to the pair
] # Close both the inner map and outer loop
Step 3: Convert this representation of the die to actual die-values of spaces and "o":
ε # Map over each value-state:
` # Pop and push both values separated to the stack
•ʒ\RN]–ä• # Push compressed integer 17448688417330322
„o Åв # Convert it to base-"o "
3ô # Split it into triplets
3ô # And then split this list of triplets into 3x3 blocks
sè # Index the current face-index into this list of 3x3 blocks
sF # Loop the rotation-state amount of times:
øí # Rotate the 3x3 block once clockwise:
ø # Zip/transpose; swapping rows/columns
í # Reverse each inner row
] # Close the inner loop and outer map
Try just steps 2 and 3 online.
Step 4: Replace the placeholder digits in the ASCII-art die of step 1 with these random and correctly oriented/rotated die-faces:
Ƶ2 # Push random integer 103
S # Convert it to a list of digits: [1,0,3]
© # Store it in variable `®` (without popping)
è # Get the die-faces at those 0-based indices
€ ̃ # Flatten each 3x3 block to a list of 9 characters
® # Push the digits [1,0,3] again
s.; # Replace every "1", "0", and "3" one by one with its 9 face-characters in the ASCII-art die string
# (after which the result is output implicitly)
See this 05AB1E tip of mine to understand how the base of the ASCII-art is generated.
See this 05AB1E tip of mine (section How to compress large integers?) to understand why •1p61⁄4ujθ2\nƵ@TV"α1⁄2[ÿTMÆÅ ́?μ1⁄4...ǝÆ2. ̃ãTMĀ"ê7‰Ć21ƵcÕ н5Å5ð ̈ôÚ• is 165694505690730716563168121971474439450718220748920420519623075258410088668853618104539042325788146223319708232484170071664982; ŽBñ is 3045; and •ʒ\RN]–ä• is 17448688417330322.
-
\$\begingroup\$ In case it makes any difference, there are of course three different axes for the last rotation; I just chose that rotation that with the
103list would minimise the number of reorientations, since Charcoal has noZipoperation. With a different string you can make all (although second operation is doubleÀso it cancels out) operations reorient all six faces, although this still requires two of the final faces to be reoriented for output. If I did this in Charcoal I wouldn't be able to use my¶to save three bytes but maybe if I used your trick of delaying the reorientations... hmm... \$\endgroup\$Neil– Neil2024年10月15日 05:04:06 +00:00Commented Oct 15, 2024 at 5:04 -
\$\begingroup\$ Well, not quite the same, but I managed to save 2 bytes from my answer by collecting my permutations up and processing them with reorientations in one go. \$\endgroup\$Neil– Neil2024年10月17日 16:25:52 +00:00Commented Oct 17, 2024 at 16:25
-
\$\begingroup\$ @Neil Nice save by combining your random loops in your answer. And I think I can indeed save some bytes on my answer here and there. Like maybe starting with a different default state instead of
152436, or indeed using different faces than those at indices1,0,3, but none of those improvements to the algorithm itself are fairly straight-forward, and rn a bit too much trouble for the maybe <3 bytes save. 🤷 So I'll probably keep it as is for now. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2024年10月17日 21:10:56 +00:00Commented Oct 17, 2024 at 21:10
JavaScript (ES6), 376 bytes
-2 thanks to @l4m2
_=>[..._+""].reduce((p,_,c)=>(q=p.split(c)).join(q.pop(n=parseInt("0d6s2o0vn9uo33hkf42s3hnk3wawr4298ves0bjvf4378gw42t9h5u068so81efteq35ft0o33ndze301xqi141wy20bmphm01n4162ogucq467q222s0j6y33937y0lfd5m0dfc0e32bgey".substr((Math.random()*24|0)*6,6),36))),`0.2.
61|
1o|
1o |
:2:o3|43 |53:43/5/4/
'2'836o6o 7-----0 5
|660 |o4
|8|3 o277-1/8/06 `).replace(/o/g,c=>(n/=2)&1?c:" ")
-
1\$\begingroup\$ Can u -1 by
_=>[..._+""].reduce((p,_,c)=>? \$\endgroup\$l4m2– l4m22024年10月14日 09:15:56 +00:00Commented Oct 14, 2024 at 9:15