# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1470: Dicey dice

From New Scientist #2631, 24th November 2007

Isabelle has a set of five dice each of which has faces showing different numbers from 1 to 6. Among them, no two pairs of opposite faces are the same, and the die with 2 opposite 4 does not have 3 opposite 6.

When her brother George recently stacked them in a single four-sided vertical column, Isabelle noticed that one side showed a run of five sequential numbers.

George then carefully moved the bottom die, without changing its orientation, to the top and Isabelle saw that the same sequence now appeared along one of the other sides.

Isabelle then tried the same move herself with a second die and George a third, and each time the original sequence was created on another side.

What pairs of opposite numbers appear on the die moved by Isabelle?

[enigma1470]

### One response to “Enigma 1470: Dicey dice”

1. Jim Randell 25 January 2013 at 9:12 am

Assuming “a run of five sequential numbers” means “five consecutive integers” (in either ascending or descending order). The following Python program finds two different solutions in 42ms.

```from itertools import permutations
from enigma import irange, printf

# the numbers used on each die
ds = list(irange(1, 6))

# use names to refer to the faces (we don't care about U/D)
(F, B, L, R) = 'FBLR'

# canonical form for a die (passed in as d = (F, B, L, R))
def canonical(d):
# the up/down pair
UD = tuple(i for i in ds if i not in d.values())
return tuple(sorted(tuple(sorted(x)) for x in ((d[F], d[B]), (d[L], d[R]), UD)))

# check the dice
def check(x):
seen = set() # record seen pairs
s24 = False # seen a die with 2/4 pair on it?
for d in x:
c = canonical(d)
# can't have 2/4 and 3/6 pairs on the same die
if (2, 4) in c and (3, 6) in c: return False
# can't have a repeated pair
if seen.intersection(c): return False
seen.update(c)
# but one of the dice must have a 2/4 pair on it
return (2, 4) in seen

# consider each die to have faces F & B and L & R
# then the possibilities for the sequence appearing are:
# F B L R, F L R B, F L B R (ignoring symmetrical duplicates)

# after the third die is moved the tower will look like:
# die  f0 f1 f2 f3
#  2    c  d  e  a
#  1    d  e  a  b
#  0    e  a  b  c
#  4    a  b  c  d
#  3    b  c  d  e
# where the consecutive sequence is: a b c d e
# appearing on face f0, f1, f2 and finally f3.

# five sequential numbers chosen from 1 to 6 are the following ascending/descending sequences
for (a, b, c, d, e) in ((1, 2, 3, 4, 5), (2, 3, 4, 5, 6), (5, 4, 3, 2, 1), (6, 5, 4, 3, 2)):
# consider faces that the sequence appears on
for (f0, f1, f2, f3) in ((F, B, L, R), (F, L, R, B), (F, L, B, R)):
# construct the dice
x = [
{ f0: e, f1: a, f2: b, f3: c }, # die 0
{ f0: d, f1: e, f2: a, f3: b }, # die 1
{ f0: c, f1: d, f2: e, f3: a }, # die 2
{ f0: b, f1: c, f2: d, f3: e }, # die 3
{ f0: a, f1: b, f2: c, f3: d }, # die 4
]
if not check(x): continue

# print the sequence
printf("sequence: {a}, {b}, {c}, {d}, {e}")
# print the tower
printf("   F B L R")
for n, i in reversed(list(enumerate(x))):
printf("{n}: {F} {B} {L} {R} {c}", F=i[F], B=i[B], L=i[L], R=i[R], c=canonical(i))
# print the 2nd die moved (in canonical form)
printf("isabelle moves die 1: {i}", i=canonical(x[1]))
printf()
```

Solution: The opposite pairs of numbers on the die moved by Isabella are: 1 and 4; 2 and 6; 3 and 5.