Determine dice value from side view

52

3

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.

user694733

Posted 2015-01-08T07:39:53.900

Reputation: 765

so I can use a table with all combination - 1 ^^? – dwana – 2015-01-08T08:17:32.540

Yes, you can use table. But you cannot use builtin compression routines to make it smaller. – user694733 – 2015-01-08T08:40:25.947

Answers

59

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.

xnor

Posted 2015-01-08T07:39:53.900

Reputation: 115 687

CJam - 26 - ri:Ari:B^7A7A-e<B7B-e<)=*^ – Optimizer – 2015-01-08T09:22:35.933

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? – xnor – 2015-01-08T09:31:42.090

Ooh, there's a/4*7^a... – xnor – 2015-01-08T09:41:25.283

11I never realized that dice face bits had this property. Nice one! – user694733 – 2015-01-08T09:43:51.343

1@user694733 It works out very fortuitously that 6 is two below a power of two. – xnor – 2015-01-08T09:44:28.533

Your 33 byte version just saves 2 bytes in CJam - l~:B\:A^7AA*7%BB4**7%=*^ from the earlier translation – Optimizer – 2015-01-08T09:52:23.927

64

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

xnor

Posted 2015-01-08T07:39:53.900

Reputation: 115 687

1FWIW, (ab)**5 % 7 == (ab)**-1 % 7 == a^b^7 for all a,b in 1..6 such that a != b and a+b != 7. – Peter Taylor – 2015-01-08T17:44:00.437

@PeterTaylor Indeed, I found that expression by using **5 as a proxy for inverting modulo 7. – xnor – 2015-01-08T17:46:08.307

mathematics ftw :) funny how the formulas like to work out in those cases – masterX244 – 2015-01-09T00:01:55.817

@rink.attendant.6 You can avoid having to take the mod of negative numbers by doing a*a + 6*b*b, guaranteeing a positive output. It's equivalent mod 7. – xnor – 2015-01-10T10:15:50.193

2

I've been losing sleep over the "why" of this amazing polynomial. Perhaps the math.SE folks can help. http://math.stackexchange.com/questions/1101870/derivation-of-dice-sides-polynimial

– Digital Trauma – 2015-01-12T22:02:27.473

1

I wrote up a derivation on math.SE: http://math.stackexchange.com/a/1101984/24654

– xnor – 2015-01-13T07:09:01.873

1You 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). – ngn – 2015-01-17T01:29:27.450

9

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

Optimizer

Posted 2015-01-08T07:39:53.900

Reputation: 25 836

Could you explain how this works? Same idea as ep1024 had? – user694733 – 2015-01-08T09:17:22.353

@user694733 not at all. Explanation added. – Optimizer – 2015-01-08T09:21:07.820

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. – user694733 – 2015-01-08T09:29:40.063

@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 :( – Teun Pronk – 2015-01-08T14:00:12.350

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. – Optimizer – 2015-01-08T14:01:22.203

5

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>

rink.attendant.6

Posted 2015-01-08T07:39:53.900

Reputation: 2 776

4

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.

es1024

Posted 2015-01-08T07:39:53.900

Reputation: 8 953

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) – FryAmTheEggman – 2015-01-08T22:20:06.080

3

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)

rink.attendant.6

Posted 2015-01-08T07:39:53.900

Reputation: 2 776

1Save 1 byte: ''+l+r => [l]+r – edc65 – 2015-01-08T10:04:04.797

@edc65 Thanks! Oh how JavaScript behaves when adding different types – rink.attendant.6 – 2015-01-08T10:09:07.293

1Yes, operator + is weird. But what about operator ~? 1+Math.floor => -~. Also, search instead of indexOf. – edc65 – 2015-01-08T10:16:52.087

Interesting. And I knew about search but it's only for ES6. – rink.attendant.6 – 2015-01-08T17:27:58.660

Actually, String.prototype.search has been part of JavaScript since ECMAScript 3rd Edition, so you can change your answer. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/search#Specifications

– kamoroso94 – 2016-08-02T14:29:09.430

3

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

ɐɔıʇǝɥʇuʎs

Posted 2015-01-08T07:39:53.900

Reputation: 4 449

0

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

EricShermanCS

Posted 2015-01-08T07:39:53.900

Reputation: 121

0

Common Lisp, 45 bytes

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

Try it online!

Port of xnor solution.

Renzo

Posted 2015-01-08T07:39:53.900

Reputation: 2 260

0

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!

dana

Posted 2015-01-08T07:39:53.900

Reputation: 2 541

149 bytes by using ("3542331463126512156236413"+x) instead of the full string – G B – 2019-01-30T14:19:25.550

0

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.

Teun Pronk

Posted 2015-01-08T07:39:53.900

Reputation: 2 599

I tested this here, and it seems to return 4 with 2 3.

– user694733 – 2015-01-08T09:40:55.183

indeed.. weird. ill look into it. – Teun Pronk – 2015-01-08T09:43:47.023

@user694733 Fixed it :) – Teun Pronk – 2015-01-08T10:08:10.437

0

PHP, 81 bytes

Same as my JavaScript solution:

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

rink.attendant.6

Posted 2015-01-08T07:39:53.900

Reputation: 2 776

0

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)

red-X

Posted 2015-01-08T07:39:53.900

Reputation: 151

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

Mark Reed

Posted 2015-01-08T07:39:53.900

Reputation: 667

0

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.

Digital Trauma

Posted 2015-01-08T07:39:53.900

Reputation: 64 644

0

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!

Adám

Posted 2015-01-08T07:39:53.900

Reputation: 37 779