52
\$\begingroup\$

Write program or function which will take left and right value of dice as integers (1-6) and return value on top.

Dice layout:

    +---+
    | 1 |
+---+---+---+---+
| 2 | 3 | 5 | 4 |
+---+---+---+---+
    | 6 |
    +---+

  ,^.
<´ 5 `>  <-- Top value
|`._,´|
.6 | 4,  <-- Side values
 `.|,´

So inputting 6 4 will return 5.

Order is important:

2 3 -> 1
3 2 -> 6

Program doesn't have to work with invalid input values.

To discourage obvious approach (using table with all combinations), using any builtin text encoding or de/compression routines or base encoding or anything else similar to reduce size is not allowed. Note that using table is still allowed and rolling your own decompression is allowed too, as long as it's not done using some ready library function.

For reference purposes, here's a table of all combinations (i.e. all possible inputs and outputs):

23, 35, 42, 54 -> 1
14, 31, 46, 63 -> 2
12, 26, 51, 65 -> 3
15, 21, 56, 62 -> 4
13, 36, 41, 64 -> 5
24, 32, 45, 53 -> 6

Shortest code wins, and standard loopholes apply.

\$\endgroup\$
  • \$\begingroup\$ so I can use a table with all combination - 1 ^^? \$\endgroup\$ – dwana Jan 8 '15 at 8:17
  • \$\begingroup\$ Yes, you can use table. But you cannot use builtin compression routines to make it smaller. \$\endgroup\$ – user694733 Jan 8 '15 at 8:40

16 Answers 16

59
\$\begingroup\$

Python, 30

lambda a,b:a^b^7*(2<a*a*b%7<5)

No lookups, just bit bashing.

The opposite faces come in pairs that are three-bit complements of each other, meaning that they XOR to 7.

1,6
2,5
3,4

Given two faces from one set, we want to get a face from the other set. For (1,2,3), we can do this with XOR (^). So, ^ gives the right answer up to three-bit complement, meaning x^7. We can conditionally complement by x^7*_.

To decide whether or not to take the complement (XOR with 7), we check whether the triplet violates the right-hand rule. That means, that a,b goes in the reverse cyclic order of

1,6
2,5
3,4

treating each line as one of the three categories. Since the elements in each line are negatives mod 7, we can "hash" them by doing x*x%7.

1,6 -> 1
2,5 -> 4
3,4 -> 2

Each line is obtained from the cyclically previous by multiplying by 4 modulo 7, so we can check whether this relationship holds for (b,a) to decide whether to complement: a*a%7==b*b*4%7.

This is equivalent to checking whether, modulo 7, a**2 * b**(-2) equals 4. Since b**6 equals 1 modulo 6, this is equivalent to a**2 * b**4. Since the other possible value is 2 (by checking cases), we can check if it's 4 by comparing to 3.

\$\endgroup\$
  • \$\begingroup\$ CJam - 26 - ri:Ari:B^7A7A-e<B7B-e<)=*^ \$\endgroup\$ – Optimizer Jan 8 '15 at 9:22
  • \$\begingroup\$ I can save a char off of min(a,7-a) by doing a^7*(a>3), but I feel like there should be a yet shorter way. Any ideas? \$\endgroup\$ – xnor Jan 8 '15 at 9:31
  • \$\begingroup\$ Ooh, there's a/4*7^a... \$\endgroup\$ – xnor Jan 8 '15 at 9:41
  • 11
    \$\begingroup\$ I never realized that dice face bits had this property. Nice one! \$\endgroup\$ – user694733 Jan 8 '15 at 9:43
  • 1
    \$\begingroup\$ @user694733 It works out very fortuitously that 6 is two below a power of two. \$\endgroup\$ – xnor Jan 8 '15 at 9:44
64
\$\begingroup\$

There's a nice polynomial expression modulo 7 for the third side given two sides a and b.

$${3(a^3b - ab^3) \mod 7}$$

or factored

$${3ab(a^2-b^2) \mod 7}$$

The modulo 7 maps to a remainder in {0,1,2,3,4,5,6}.

I explain why it works in this Math SE answer, though I do think there probably is a cleaner argument I'm missing. The only other two-term polynomial that works is

$${(3a^5b^5 - a^3b) \mod 7}$$

which I originally found by transforming my bit-bashing into arithmetic operations, then did a brute-force search over polynomials of this form to find the nicer one.

Please feel free to add ports of this into your favorite language; this is a CW post.

J, 9 by Synthetica

7|3***+*-

See my post

Dyalog APL, 9 by ngn (typo fixed by Adám)

7|3×××+×-

Blatantly stolen from above J answer.

TI-Basic, 14 by Timtech

7fPart((A³B-AB³)/21

Pyth, 16 by FryAmTheEggman

M%*3-*H^G3*^H3G7

Defines a function g of two values.

Golfscript, 18 by Peter Taylor (old polynomial)

~1$*.5?3*@.*@*- 7%

CJam, 18 by Martin Büttner (ported from Peter's GolfScript) (old polynomial)

l~1$*_5#3*@_*@*m7%

Mathematica, 20 by Martin Büttner

Mod[+##(#-#2)3##,7]&

Yes, that's a unary plus, and no, there's no shorter way that doesn't use a unary plus.

dc, 21 by Toby Speight

sb7+d3^lb*rlb3^*-3*7%

I have to add 7 to a to ensure the difference is always positive (dc has a signed % operator).

Julia, 24 23 by Martin Büttner

f(a,b)=3a*b*(a^2-b^2)%7

CoffeeScript, 28 26 by rink.attendant.6

x=(a,b)->3*a*b*(a*a-b*b)%7

JavaScript (ES6), 28 26 by rink.attendant.6

x=(a,b)=>3*a*b*(a*a-b*b)%7

Essentially the same as CoffeeScript.

Python 28, by xnor

lambda a,b:3*a*b*(a*a-b*b)%7

Bash, 31

Nothing special:

echo $[3*($1**3*$2-$1*$2**3)%7]

or alternatively:

echo $[3*$1*$2*($1*$1-$2*$2)%7]

Another (longer but perhaps interesting) approach.

Nim, 36 by Sillesta

proc(x,y:int):int=3*x*y*(x*x-y*y)%%7

Java 7, 46 44 by rink.attendant.6

int f(int a,int b){return(a*a-b*b)*a*b*3%7;}

Java 8, 25 23 by Kevin Cruijssen

a->b->(a*a-b*b)*a*b*3%7

PHP, 49 47 by rink.attendant.6

function x($a,$b){echo($a*$a-$b*$b)*3*$a*$b%7;}

Batch, 52 unclemeat

set/aa=(3*(%1*%1*%1*%2-%1*%2*%2*%2)%%7+7)%%7
echo %a%

CMD does not support true modulus natively (so can't handle negative numbers) - hence %%7+7)%%7.

LESS (as a parametric mixin), 62 60 by rink.attendant.6

.x(@a,@b){@r:mod(3*@a*@b*(@a*@a-@b*@b),7);content:~"'@{r}'"}

See my post below.

05AB1E, 10 8 by Emigna (-2 bytes by Kevin Cruijssen)

nÆs`3P7%

Try it online.

Haskell, 31 27 25 by Generic Display Name

a#b=3*a*b*(a*a-b*b)`mod`7

Try it online!

Excel, 27 by by Wernisch

=MOD(3*(A1^3*B1-A1*B1^3),7)

Excel VBA, 25 by Taylor Scott

?3*[A1^3*B1-A1*B1^3]Mod 7

Forth (gforth) 41 by reffu

: f 2>r 2r@ * 2r@ + 2r> - 3 * * * 7 mod ;

Try it online!

C#, 23 by Kevin Cruijssen

a=>b=>(a*a-b*b)*a*b*3%7
\$\endgroup\$
  • 1
    \$\begingroup\$ FWIW, (ab)**5 % 7 == (ab)**-1 % 7 == a^b^7 for all a,b in 1..6 such that a != b and a+b != 7. \$\endgroup\$ – Peter Taylor Jan 8 '15 at 17:44
  • \$\begingroup\$ @PeterTaylor Indeed, I found that expression by using **5 as a proxy for inverting modulo 7. \$\endgroup\$ – xnor Jan 8 '15 at 17:46
  • 2
    \$\begingroup\$ I've been losing sleep over the "why" of this amazing polynomial. Perhaps the math.SE folks can help. math.stackexchange.com/questions/1101870/… \$\endgroup\$ – Digital Trauma Jan 12 '15 at 22:02
  • 1
    \$\begingroup\$ I wrote up a derivation on math.SE: math.stackexchange.com/a/1101984/24654 \$\endgroup\$ – xnor Jan 13 '15 at 7:09
  • 1
    \$\begingroup\$ You can rewrite the APL train as 7|3×××+×-, pronounced: 7-remainder of 3 times the product times the sum times the difference (between the two numbers). \$\endgroup\$ – ngn Jan 17 '15 at 1:29
9
\$\begingroup\$

CJam, 43 28 bytes

No idea if a full table based approach will be shorter, but here goes:

l_~^56213641532453s@S-#)g7*^

Input like

2 3

Output:

1

This is a mixture of my previous algorithm to determine the correct face out of 2 faces and xnor's approach of xors.

Try it online here

\$\endgroup\$
  • \$\begingroup\$ Could you explain how this works? Same idea as ep1024 had? \$\endgroup\$ – user694733 Jan 8 '15 at 9:17
  • \$\begingroup\$ @user694733 not at all. Explanation added. \$\endgroup\$ – Optimizer Jan 8 '15 at 9:21
  • \$\begingroup\$ Yeah, I saw the time. I was just wondering if it's similar, because he had explanation on it, and I have no idea how CJam works. \$\endgroup\$ – user694733 Jan 8 '15 at 9:29
  • \$\begingroup\$ @Optimizer I want to get started on CJam too, any general direction you can point me at for tutorials etc? I see some examples but they hardly have any explaination :( \$\endgroup\$ – Teun Pronk Jan 8 '15 at 14:00
  • \$\begingroup\$ The link above have some examples and a link to the main website which has explanations of the language keywords. Other than that, search here with cjam keyword to learn from existing answers. \$\endgroup\$ – Optimizer Jan 8 '15 at 14:01
5
\$\begingroup\$

LESS, 62 bytes

Uses the algorithm in this post:

.x(@a,@b){@r:mod(3*@a*@b*(@a*@a+6*@b*@b),7);content:~"'@{r}'"}

It could be shorter if the integer value was used, but to get it to display I needed to use the CSS content property which required variable interpolation.

Nonetheless, it's not often that a CSS preprocessor language is used for code golf!

To use with some HTML, you'd do this:

p::after { .x(1, 3); }
<p>Number on top: </p>
\$\endgroup\$
4
\$\begingroup\$

Pyth, 30 bytes

K"23542 31463 12651 "h/x+K_Kz6

Requires the two digits as input, with no space in between (ex. 23 not 2 3).

Explanation:

Any two digit sequence that lies within 23542 represents two sides that have 1 on top. Likewise, 31463 for 2, etc. Reversing this string gives the sequences for 4 through 6.

This code just does a lookup in the string "23542 31463 12651 15621 36413 24532", divides the index by 6, and increments to determine what the top side must be.

Test online here.

Thanks to @FryAmTheEggman for tips on golfing this.

\$\endgroup\$
  • \$\begingroup\$ Some pyth-related golfs: J"23542 31463 12651 "h/x+J_Jscz)6 Ping me if some of it is confusing. Prefer K and J for assigning values, h is unary +1, s on a list of strings is jk. (Also, if allowed, just using a string like 23 as the input would be best) \$\endgroup\$ – FryAmTheEggman Jan 8 '15 at 22:20
3
\$\begingroup\$

Takes a similar approach as es1024 with a different lookup string:

JavaScript (ES6), 73 72 61 bytes

t=(l,r)=>-~('354233146312651215623641332453'.search([l]+r)/5)

JavaScript (ES5), 88 87 77 bytes

function t(l,r){return -~('354233146312651215623641332453'.indexOf([l]+r)/5)}

CoffeeScript, 71 62 bytes

And just for the fun of it, the code is 1 byte shorter in CoffeeScript as ES6 due to the permitted omission of parentheses

Due to the use of the -~ trick, this turned out to be the same number of characters as ES6.

t=(l,r)->-~('354233146312651215623641332453'.indexOf([l]+r)/5)
\$\endgroup\$
  • 1
    \$\begingroup\$ Save 1 byte: ''+l+r => [l]+r \$\endgroup\$ – edc65 Jan 8 '15 at 10:04
  • \$\begingroup\$ @edc65 Thanks! Oh how JavaScript behaves when adding different types \$\endgroup\$ – rink.attendant.6 Jan 8 '15 at 10:09
  • 1
    \$\begingroup\$ Yes, operator + is weird. But what about operator ~? 1+Math.floor => -~. Also, search instead of indexOf. \$\endgroup\$ – edc65 Jan 8 '15 at 10:16
  • \$\begingroup\$ Interesting. And I knew about search but it's only for ES6. \$\endgroup\$ – rink.attendant.6 Jan 8 '15 at 17:27
  • \$\begingroup\$ Actually, String.prototype.search has been part of JavaScript since ECMAScript 3rd Edition, so you can change your answer. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… \$\endgroup\$ – kamoroso94 Aug 2 '16 at 14:29
3
\$\begingroup\$

J (9)

Uses the algorithm from this post.

7|3***+*-

Tree graph of the function (might clear some things up):

    f=:7|3***+*-
    f
7 | 3 * * * + * -
   5 !: 4 < 'f'
  ┌─ 7            
  ├─ |            
──┤   ┌─ 3        
  │   ├─ *        
  └───┤   ┌─ *    
      │   ├─ *    
      └───┤   ┌─ +
          └───┼─ *
              └─ -

Demonstration:

   3 f 5
1
   4 f 6
2
   2 f 6
3
   2 f 1
4
   1 f 2
3
   4 f 5
6
\$\endgroup\$
0
\$\begingroup\$

PHP, 81 bytes

Same as my JavaScript solution:

function t($l,$r){echo(int)(1+strpos('354233146312651215623641332453',$l.$r)/5);}
\$\endgroup\$
0
\$\begingroup\$

Lua 118

Had to restore last version because of a bug I can't find, nor have time to look for it.

z=io.read;o={"","","34","5 2","2165","46 13",""," 31064","  5612","   2 5","    43"}a=z();b=z();print(o[a+b]:sub(a,a))

Still working on this though.

\$\endgroup\$
  • \$\begingroup\$ I tested this here, and it seems to return 4 with 2 3. \$\endgroup\$ – user694733 Jan 8 '15 at 9:40
  • \$\begingroup\$ indeed.. weird. ill look into it. \$\endgroup\$ – Teun Pronk Jan 8 '15 at 9:43
  • \$\begingroup\$ @user694733 Fixed it :) \$\endgroup\$ – Teun Pronk Jan 8 '15 at 10:08
0
\$\begingroup\$

JavaScript (ES6), 79 bytes

Not the shortest but I tried a different approach than currently in the answers.

f=(a,b)=>[a,b,7-a,7-b].reduce((p,v,i,r)=>p?p:'2312132'.indexOf([v]+r[i+1])+1,0)
\$\endgroup\$
0
\$\begingroup\$

Lua, 89 bytes

A straightforward port of xnor's Python solution.

x=require('bit32').bxor
function(a,b)c=a*a*b%7;return x(a,x(b,2<c and c<5 and 7 or 0))end
\$\endgroup\$
0
\$\begingroup\$

Bash, 85

This doesn't compete golf-wise with @xnor's magic polynomial. But I think this is another interesting way to calculate the answer:

g(){
((d[$1$2]))||{
d[$1$2]=$3
g $2 $1 $[7-$3]
g $2 $3 $1
}
}
g 1 2 3
echo ${d[$1$2]}

Specifically we know the the following about dice:

  • If the left face is 1 and the right face is 2, then the top face is 3
  • Rotation around opposite vertices by 120° gives some more triples of face values. E.g we rotate {l=1,r=2,t=3} once we get {l=2,r=3,t=1} and rotating again we get {l=3,r=1,t=2}
  • The sum of opposite faces is always 7

Combining the above recursively (using {1,2,3} hardcoded as a starting point), we can generate the entire mapping of {l,r}->t for all possible values. This answer defines a recursive function g() that populates a full array such that d[lr]=t. The recursive function is initially called with {1,2,3} and recurses all over the whole cube until there are no more array elements that have not been set. The function recurses into itself in two ways:

  • with l and r swapped and t subtracted from 7 (opposite faces)
  • with {l,r,t} rotated to {r,t,l}

It then does a simple array lookup of the values required.

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

Dyalog APL, 9 bytes

Blatant character substitution of ɐɔıʇǝɥʇuʎs's J solution:

7|3×××+×-

Edit: I later noticed that this exact solution was suggested by ngn on Jan 17, 15.

  the division remainder when divided by seven of
  |        three times
  |        | the product of the arguments
  |        |   times   \┌───┐
  |        |     \  ┌───┤ × │
┌────┐   ┌────┐   ┌─┴─┐ └───┘ ┌───┐
│ 7| ├───┤ 3× ├───┤ × │   ┌───┤ + │ - the sum of the arguments
└────┘   └────┘   └─┬─┘ ┌─┴─┐ └───┘      
                    └───┤ × │ ---- times
                        └─┬─┘ ┌───┐
                          └───┤ - │ - the difference between the arguments
                              └───┘

TryAPL online!

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

Julia, 26 bytes

f(a,b)=a$b$7*(2<a^2*b%7<5)

or

f(a,b)=(3*a^5*b^5-a^3*b)%7

or

f(a,b)=3*a*b*(a+b)*(a-b)%7
\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 45 bytes

(lambda(a b)(mod(* 3 a b(-(* a a)(* b b)))7))

Try it online!

Port of xnor solution.

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

C# (Visual C# Interactive Compiler), 49 bytes

x=>1+("3542331463126512156236413"+x).IndexOf(x)/5

Try it online!

-1 byte thanks to @GB!

The input is a 2 character string containing the visible left and right digits.

Below is the solution that I came up with independently. Leveraging the lookup string from rink.attendant.6's JavaScript answer, I was able to shave off 5 bytes (but now our answers are pretty similar ;)

C# (Visual C# Interactive Compiler), 55 bytes

x=>1+"42354 31463 51265 21562 41364 24532".IndexOf(x)/6

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ 49 bytes by using ("3542331463126512156236413"+x) instead of the full string \$\endgroup\$ – G B Jan 30 at 14:19

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.