15
\$\begingroup\$

In a standard dice (die) the numbers are arranged so that opposite faces add to seven. Write the shortest possible program in your preferred language which outputs a random throw followed by 9 random tippings. A tipping is a quarter turn of the dice, e.g. if the dice is facing 5, all possible tippings are 1,3,4 and 6.

Example of desired output:

1532131356

\$\endgroup\$

20 Answers 20

9
\$\begingroup\$

Ruby, 44

c=0;10.times{$><<c=([*1..6]-[c,7-c]).sample}

I found the [*1..6] trick by lucky experimenting.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Some nice tricks here, great stuff. Hitting myself on the head for missing the Array#sample method. \$\endgroup\$ Feb 21, 2011 at 8:49
5
\$\begingroup\$

GolfScript, 26 chars

0{(.6,5@--\-.,rand=).}10*;

A slight more compressed version of Joey's, basically working around the issue with zero-indexing.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (71 characters)

You may need to replace print with alert or something else, depending on your JavaScript environment.

for(C=L=T=0;C++<10;print(L=T))while(!(T-L&&T+L-7))T=Math.random()*6+1|0
\$\endgroup\$
1
  • \$\begingroup\$ merge loops by conditionally incrementing the outer one when a value is found : for(b=n=10;n;a-b&&a+b-7&&print(b=a,n--))a=Math.random()*6+1|0 \$\endgroup\$
    – imma
    Feb 25, 2014 at 10:53
4
\$\begingroup\$

GolfScript, 28

0:|;{7,[0|7|-]-.,rand=:|}10*
\$\endgroup\$
3
\$\begingroup\$

Bash

#/!bin/bash
f=`expr $RANDOM % 6` 
f=`expr $f + 1`
printf "$f"
for ((i=0; i<9; i++))
do
   ((bad=7-$f))
   next=`expr $RANDOM % 6`
   next=`expr $next + 1`
   while [ $next -eq $bad ] || [ $next -eq $f ]
   do
      next=`expr $RANDOM % 6`
      next=`expr $next + 1`
   done
printf "$next"
f=$next
done

sample code: http://ideone.com/CCfro

\$\endgroup\$
2
  • \$\begingroup\$ The use of ((var=expression)) is very nice - I thought that the shortest way was var=$((expression)) But why do you use that once only and waste tonnes of characters on expr in backticks? \$\endgroup\$ Feb 16, 2011 at 10:00
  • \$\begingroup\$ I dont do much of shell scripting, but for some reason ((var=expr)) in some places got failed (yeah weird :P ) Since I started this script, I just somehow completed. :) \$\endgroup\$ Feb 16, 2011 at 11:10
3
\$\begingroup\$

Bash: 97 94 92 90 89 87

Heavily golfed from Aman ZeeK Verma's answer:

for((i=10,f=0;i--;))do
for((n=f;n==f||n+f==7;f=RANDOM%6+1))do :
done
printf $f
done

http://ideone.com/QiuTx

NB arguably it can be shrunk by 5 chars by changing the first line to for((;i++<10;)) but that makes assumptions which aren't always valid. It would work ok in ideone but someone running it from a shell could have i or f exported to something non-zero.

\$\endgroup\$
3
  • \$\begingroup\$ I'd like to do a version without the inner loop, but I fear it will be longer. \$\endgroup\$ Feb 16, 2011 at 11:06
  • \$\begingroup\$ This is extremely awesome, I am too raw for bash I guess :) \$\endgroup\$ Feb 16, 2011 at 11:11
  • \$\begingroup\$ @Aman, most of it isn't bash-specific. It's just several dozen refinements with tests after each one and reversions when I broke something. The only bit which is really a bash trick is the noop, which I had to look up. If you have time to read man bash, though, I recommend it. I once read it cover to cover, and just having a vague idea of what's possible and worth looking up has served me well. \$\endgroup\$ Feb 16, 2011 at 11:36
3
\$\begingroup\$

R, 56 52

for(i in 0:9)cat(F<-sample(setdiff(1:6,c(F,7-F)),1))
\$\endgroup\$
3
2
\$\begingroup\$

Bash with only one loop: 100 99 98 96

for((i=10,f=RANDOM%6+1;i--;))do
printf $f
((n=RANDOM%4+1,m=f<4?f:7-f,f=n<m||++n<7-m?n:n+1))
done

http://ideone.com/XrZO7

The key idea is that to pick a random number in [1,x] which isn't equal to y you can pick a random number in [1,x-1] and then increment if it's >= y. For this problem we want a random number in [1,6] which isn't equal to f or 7-f. We have to do the two tests in order min(f,7-f), max(f,7-f).

Assuming an initially empty environment could save 2 chars by not initialising i and changing the loop condition to i++<10

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

Windows PowerShell, 45

-join(0..9|%{($d=1..6-ne(7-$d)-ne$d|random)})

Pretty trivial, actually. I generate a list of possible dice rolls 1..6 and then select only those not equal to seven minus the last roll and then only those not equal to the last roll. From the remaining list I then select a random item and assign it to $d. Since $d is initially treated as 0 it rolls a normal die the first time.

Test script:

for($i=0;$i-lt20;$i++){
    $o=@(./tipping.ps1)
    if ($i-gt0-and$o-eq$o2) { throw "Must have random output" }
    if ($o.count-ne1) { throw "Must only have one line of output" }
    if ($o[0]-match'[^1-6]'){ throw "Invalid characters" }
    if($o[0].length-ne10){ throw "Wrong length: $($o[0].length)" }
    $r=[char[]]($o[0])|%{$_-48}
    for ($x=1;$x-lt$r.count;$x++){
        if ($r[$x-1]+$r[$x]-eq7) { throw "Not a tipping: $($r[$x-1]) and $($r[$x])" }
    }
    $o2=$o
}

History:

  • 2011-02-18 11:57 (61) First attempt.
  • 2011-02-18 11:58 (45) I don't need to generate the first number separately.
\$\endgroup\$
2
  • \$\begingroup\$ I get The term 'random' is not recognized as a cmdlet, function, operable program, or script file. Verify the term and try again. \$\endgroup\$ Feb 18, 2011 at 12:17
  • \$\begingroup\$ @Peter: PowerShell v2, please. The Get-Random cmdlet didn't exist in v1. \$\endgroup\$
    – Joey
    Feb 18, 2011 at 12:46
2
\$\begingroup\$

J

This should work but unfortunately J's random generator gets stuck after the 3rd iteration:

a=:>:i.6
f=:a#~1-(+&(a=])7&-)
((,(?4)&{@f@(_1&{))^:9)>:?6

6 4 5 4 5 4 5 4 5 4

\$\endgroup\$
1
  • \$\begingroup\$ I'm by no measure a J expert, but it seems to me from what I suffered composing my J answer to this thread that (?4) tends to be rolled once and treated as a constant for subsequent iterations if you're not careful around it. I worked around it using a (?@4:)-like construct. \$\endgroup\$
    – J B
    Feb 16, 2011 at 12:48
2
\$\begingroup\$

Ruby

66 characters

(0..9).reduce([]){|m|m<<((1..6).to_a-[d=m[-1]||0,7-d]).shuffle[0]}
\$\endgroup\$
2
\$\begingroup\$

J, 30 characters

>:(?@4:{(i.6)-.],5&-)^:(<10)?6

6 2 3 5 4 2 4 1 3 6

Explanations (read from right to left):

  • ?6 returns a random number between 0 and 5
  • ^:(<10) applies a function 9 times, accumulating the results along the way. The function is:
  • ?@4:{(i.6)-.],5&-
    • ] , 5&- returns an array of the input number and its complement to 5 (we're handling 0-based numbers currently, so the sum of opposite faces is 5)
    • (i. 6) -. removes them from the full set of integers 0 to 5. We're left with all valid positions after a single tipping operation from the input position.
    • ?@4: { picks one of those at random.
  • >: increments the whole sequence to bring the figures back to the 1 to 6 interval.
\$\endgroup\$
2
  • \$\begingroup\$ Nice thought to ">:" at then end. \$\endgroup\$
    – Eelvex
    Feb 15, 2011 at 23:48
  • 1
    \$\begingroup\$ @Eelvex I have no idea why real-world dice are 1 to 6 when all sensible reasoning about them uses 0 to 5. :D \$\endgroup\$
    – J B
    Feb 16, 2011 at 12:49
2
\$\begingroup\$

TI-BASIC, 38 34

For(I,1,9
Ans→X
Repeat Ans≠X and Ans≠7-X
randInt(1,6
End
Disp Ans
End

Boring solution, but it's shorter than the previous revision. I take advantage of the fact that on a fresh calculator, Ans is initialized to zero.

\$\endgroup\$
3
  • \$\begingroup\$ I don't know if it's possible, but I'll give 50 rep to anyone who can find a shorter solution. \$\endgroup\$
    – lirtosiast
    Oct 5, 2015 at 2:58
  • \$\begingroup\$ How are you calculating 34? \$\endgroup\$
    – recursive
    Oct 5, 2015 at 6:20
  • \$\begingroup\$ Each token here is one byte in memory; it's standard for TI-BASIC to be scored this way. If you have a calculator, type the program in, look at the memory management screen, then subtract 9 and subract the length of the program's name to get the code size. \$\endgroup\$
    – lirtosiast
    Oct 5, 2015 at 16:47
2
\$\begingroup\$

GS2, 16 bytes

16 2f 25 08 41 20 17 30 16 2f 31 31 25 09 19 32

Here's how it works

16 2f 25     # make range from 1 to 6 and push random element
08           # start block
    41       # duplicate top of stack twice
    20 17 30 # negate top of stack and add 7
    16 2f    # push range from 1 to 6
    31 31    # do set-wise difference with each of the two previous numbers
    25       # push a random element from the list
09           # end block
19 32        # repeat block 9 times
\$\endgroup\$
1
  • \$\begingroup\$ I think gs2 is newer than this challenge. \$\endgroup\$
    – lirtosiast
    Oct 5, 2015 at 17:19
1
\$\begingroup\$

QBasic (71 characters)

The two newlines are necessary and included in the character count as one character each.

RANDOMIZE:FOR I=0TO 9
1N=INT(RND*6)+1:IF L=N OR L+N=7THEN 1
?N:L=N:NEXT
\$\endgroup\$
1
\$\begingroup\$

Java 8, 130 bytes

v->{int d=(int)(Math.random()*6+1),i=10,p;String r=""+d;for(;i-->0;r+=d)for(p=d;p==d|p+d==7;d=(int)(Math.random()*6+1));return r;}

Try it here.

As full program with verbose main-method this would be 178 bytes instead:

interface M{static void main(String[]a){int d=(int)(Math.random()*6+1),i=10,p;String r=""+d;for(;i-->0;r+=d)for(p=d;p==d|p+d==7;d=(int)(Math.random()*6+1));System.out.print(r);}}

Try it here.

Semi-port of @AmanZeeKVerma's Bash answer.

Explanation:

 v->{              // Method with empty unused parameter and String return-type
   int d=(int)(Math.random()*6+1),
                   //  Random dice-roll 1-6
       i=10,       //  Counter-integer, starting at 10
       p;          //  Temp integer to store new side
   String r=""+d;  //  Result-String, starting at the first dice-roll
   for(;i-->0;     //  Loop (1) 10 times:
       r+=d)       //    After every iteration, append the result with a random side
     for(p=d;      //   Set the new side to the current side
         p==d      //   Loop (2) as long as the new side and current side are the same
         |p+d==7;  //   or as long as both combined are exactly 7:
       d=(int)(Math.random()*6+1)
                   //    Set the new side to a random side 1-6
     );            //   End of loop (2)
                   //  End of loop (1) (implicit / single-line body)
  return r;        //  Return the result-String
}                  // End of method
\$\endgroup\$
1
\$\begingroup\$

MATLAB 58 bytes

a=randi(6)
for i=1:9;b=1:6;b([a,7-a])=[];a=b(randi(4))
end
\$\endgroup\$
0
\$\begingroup\$

><>, 71 bytes

I'm glad I could showcase ><>'s x code-pointer randomization as I don't recall seeing it here.

a&0 v
 /2v
1x3v 
>x< <<
6x4v
 \5v ~
:{:/ ^?=}
:{:/ ^?=7+}
:~$<^&;!?:-1&n

You can try it on this online interpreter (paste code, submit, start).

\$\endgroup\$
2
  • \$\begingroup\$ You'll get my upvote once you fix the solution. \$\endgroup\$
    – lirtosiast
    Oct 5, 2015 at 21:08
  • \$\begingroup\$ @ThomasKwa Done, I might be able to golf it down a little bit but at least it's now functional. \$\endgroup\$
    – Aaron
    Oct 6, 2015 at 6:12
0
\$\begingroup\$

R, 67 bytes

c(3,5,1,4,2,6)[(sample(1:6,1)+cumsum(sample((-2:2)[-3],9,T)))%%6+1]

Try it online!

There is a golfier R answer but this I think is a different approach from the answers submitted so far.

c(3,5,1,4,2,6)                                                     #A dice and its facets
               (sample(1:6,1)                                      #Initial dice roll
                             +cumsum(sample((-2:2)[-3],9,T)))      #9 tippings in c(-2,-1,1,2)
                                                             %%6+1 #converts to values in [0,6]
              [                                                   ]#
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 23 bytes

6LΩUTFX?6LʒDXÊsX+7Ê*}ΩU

Can definitely be golfed, but I'm currently not seeing it..

Try it online.

Explanation:

6LΩ              # Pick a random value from the range [1,6]
                 #  i.e. [1,2,3,4,5,6] → 3
   U             # Save this random value in variable `X`
TF               # Loop 10 times:
  X?             #  Print `X` without newline to STDOUT
  6Lʒ     }      #  Create a range [1,6] again, and filter it by:
     DXÊ         #   Check if the current value is not equal to `X`
                 #    i.e. 1 and 3 → 1 (truthy)
                 #    i.e. 3 and 3 → 0 (falsey)
     sX+         #   Sum the current value with `X`
                 #    i.e. 1 and 3 → 4
                 #    i.e. 3 and 3 → 6
        7Ê       #   And check if it's not equal to 7
                 #    i.e. 4 and 7 → 1 (truthy)
                 #    i.e. 6 and 7 → 1 (truthy)
     *           #   If both checks are truthy, keep it in the filtered list
                 #    i.e. 1 and 1 → 1 (truthy)
                 #    i.e. 0 and 1 → 0 (falsey)
           Ω     #  Pick a random value from the filtered list
                 #   i.e. [1,2,5,6] → 1
            U    #  And save it in variable `X` for the next iteration of the loop
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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