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.
-
\$\begingroup\$ so I can use a table with all combination - 1 ^^? \$\endgroup\$dwana– dwana2015年01月08日 08:17:32 +00:00Commented Jan 8, 2015 at 8:17
-
\$\begingroup\$ Yes, you can use table. But you cannot use builtin compression routines to make it smaller. \$\endgroup\$user694733– user6947332015年01月08日 08:40:25 +00:00Commented Jan 8, 2015 at 8:40
16 Answers 16
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)
×ばつ-
Blatantly stolen from above J answer.
TI-Basic, 14 by Timtech
7fPart((A3B-AB3)/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 (削除ここまで) 21 by Martin Büttner, fixed by MarcMush
a\b=(3a^5*b^4-a^3)b%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%
Haskell, (削除) 31 (削除ここまで) (削除) 27 (削除ここまで) 25 by Generic Display Name
a#b=3*a*b*(a*a-b*b)`mod`7
Excel, 27 by by Wernisch
=MOD(3*(A1^3*B1-A1*B1^3),7)
Excel VBA, 25 by Taylor Raine
?3*[A1^3*B1-A1*B1^3]Mod 7
Forth (gforth) 41 by reffu
: f 2>r 2r@ * 2r@ + 2r> - 3 * * * 7 mod ;
C#, 23 by Kevin Cruijssen
a=>b=>(a*a-b*b)*a*b*3%7
Jelly, 9 by caird coinheringaahing
_×ばつ3%7
Exactly the same as the J and APL answers, but in reverse
-
1\$\begingroup\$ FWIW,
(ab)**5 % 7 == (ab)**-1 % 7 == a^b^7for alla,bin1..6such thata != banda+b != 7. \$\endgroup\$Peter Taylor– Peter Taylor2015年01月08日 17:44:00 +00:00Commented Jan 8, 2015 at 17:44 -
\$\begingroup\$ @PeterTaylor Indeed, I found that expression by using
**5as a proxy for inverting modulo 7. \$\endgroup\$xnor– xnor2015年01月08日 17:46:08 +00:00Commented Jan 8, 2015 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– Digital Trauma2015年01月12日 22:02:27 +00:00Commented Jan 12, 2015 at 22:02
-
1\$\begingroup\$ I wrote up a derivation on math.SE: math.stackexchange.com/a/1101984/24654 \$\endgroup\$xnor– xnor2015年01月13日 07:09:01 +00:00Commented Jan 13, 2015 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– ngn2015年01月17日 01:29:27 +00:00Commented Jan 17, 2015 at 1:29
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.
-
\$\begingroup\$ CJam - 26 -
ri:Ari:B^7A7A-e<B7B-e<)=*^\$\endgroup\$Optimizer– Optimizer2015年01月08日 09:22:35 +00:00Commented Jan 8, 2015 at 9:22 -
\$\begingroup\$ I can save a char off of
min(a,7-a)by doinga^7*(a>3), but I feel like there should be a yet shorter way. Any ideas? \$\endgroup\$xnor– xnor2015年01月08日 09:31:42 +00:00Commented Jan 8, 2015 at 9:31 -
\$\begingroup\$ Ooh, there's
a/4*7^a... \$\endgroup\$xnor– xnor2015年01月08日 09:41:25 +00:00Commented Jan 8, 2015 at 9:41 -
11\$\begingroup\$ I never realized that dice face bits had this property. Nice one! \$\endgroup\$user694733– user6947332015年01月08日 09:43:51 +00:00Commented Jan 8, 2015 at 9:43
-
1\$\begingroup\$ @user694733 It works out very fortuitously that 6 is two below a power of two. \$\endgroup\$xnor– xnor2015年01月08日 09:44:28 +00:00Commented Jan 8, 2015 at 9:44
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.
-
\$\begingroup\$ Could you explain how this works? Same idea as ep1024 had? \$\endgroup\$user694733– user6947332015年01月08日 09:17:22 +00:00Commented Jan 8, 2015 at 9:17
-
\$\begingroup\$ @user694733 not at all. Explanation added. \$\endgroup\$Optimizer– Optimizer2015年01月08日 09:21:07 +00:00Commented Jan 8, 2015 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– user6947332015年01月08日 09:29:40 +00:00Commented Jan 8, 2015 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– Teun Pronk2015年01月08日 14:00:12 +00:00Commented Jan 8, 2015 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– Optimizer2015年01月08日 14:01:22 +00:00Commented Jan 8, 2015 at 14:01
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>
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.
Thanks to @FryAmTheEggman for tips on golfing this.
-
\$\begingroup\$ Some pyth-related golfs:
J"23542 31463 12651 "h/x+J_Jscz)6Ping me if some of it is confusing. PreferKandJfor assigning values,his unary+1,son a list of strings isjk. (Also, if allowed, just using a string like23as the input would be best) \$\endgroup\$FryAmTheEggman– FryAmTheEggman2015年01月08日 22:20:06 +00:00Commented Jan 8, 2015 at 22:20
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)
-
1\$\begingroup\$ Save 1 byte:
''+l+r=>[l]+r\$\endgroup\$edc65– edc652015年01月08日 10:04:04 +00:00Commented Jan 8, 2015 at 10:04 -
\$\begingroup\$ @edc65 Thanks! Oh how JavaScript behaves when adding different types \$\endgroup\$rink.attendant.6– rink.attendant.62015年01月08日 10:09:07 +00:00Commented Jan 8, 2015 at 10:09
-
1\$\begingroup\$ Yes, operator + is weird. But what about operator ~?
1+Math.floor=>-~. Also, search instead of indexOf. \$\endgroup\$edc65– edc652015年01月08日 10:16:52 +00:00Commented Jan 8, 2015 at 10:16 -
\$\begingroup\$ Interesting. And I knew about
searchbut it's only for ES6. \$\endgroup\$rink.attendant.6– rink.attendant.62015年01月08日 17:27:58 +00:00Commented Jan 8, 2015 at 17:27 -
\$\begingroup\$ Actually,
String.prototype.searchhas 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– kamoroso942016年08月02日 14:29:09 +00:00Commented Aug 2, 2016 at 14:29
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
PHP, 81 bytes
Same as my JavaScript solution:
function t($l,$r){echo(int)(1+strpos('354233146312651215623641332453',$l.$r)/5);}
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.
-
\$\begingroup\$ I tested this here, and it seems to return
4with2 3. \$\endgroup\$user694733– user6947332015年01月08日 09:40:55 +00:00Commented Jan 8, 2015 at 9:40 -
\$\begingroup\$ indeed.. weird. ill look into it. \$\endgroup\$Teun Pronk– Teun Pronk2015年01月08日 09:43:47 +00:00Commented Jan 8, 2015 at 9:43
-
\$\begingroup\$ @user694733 Fixed it :) \$\endgroup\$Teun Pronk– Teun Pronk2015年01月08日 10:08:10 +00:00Commented Jan 8, 2015 at 10:08
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)
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
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.
Dyalog APL, 9 bytes
Blatant character substitution of ɐɔıʇǝɥʇuʎs's J solution:
×ばつ-
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| ├───┤ ×ばつ ├───┤ ×ばつ │ ┌───┤ + │ - the sum of the arguments
└────┘ └────┘ └─┬─┘ ┌─┴─┐ └───┘
└───┤ ×ばつ │ ---- times
└─┬─┘ ┌───┐
└───┤ - │ - the difference between the arguments
└───┘
TryAPL online!
Julia, 26 bytes
f(a,b)=a$b7ドル*(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
Common Lisp, 45 bytes
(lambda(a b)(mod(* 3 a b(-(* a a)(* b b)))7))
Port of xnor solution.
C# (Visual C# Interactive Compiler), 49 bytes
x=>1+("3542331463126512156236413"+x).IndexOf(x)/5
-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
-
1\$\begingroup\$ 49 bytes by using ("3542331463126512156236413"+x) instead of the full string \$\endgroup\$G B– G B2019年01月30日 14:19:25 +00:00Commented Jan 30, 2019 at 14:19