# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1355: Cube words

From New Scientist #2514, 27th August 2005

Mitch has 27 small wooden cubes and each has a letter on it. He builds the cubes into a large 3×3×3 cube with the vertical sides running east-west and north-south. He reads off 27 three-letter words from the large cube as follows:

9 are vertical columns which he reads from top to bottom;
9 are horizontal rows which run from west to east and which he read from west to east;
9 are horizontal rows which run north to south and which he reads from north to south.

The 27 words he reads off are:

acb, aeb, afd, bae, baf, bcd, bce, bde, bec, cbe, cda, cef, cfe, daf, dba, dca, dea, dfe, ebc, ebd, edc, efa, efb, efd, fab, feb, fec.

Which are the three words that go though the centre of the large cube?

[enigma1355]

### One response to “Enigma 1355: Cube words”

1. Jim Randell 16 January 2014 at 7:41 am

This Python program uses a recursive solver to assign each of the words given to one of the possible groupings of cubes. To make it run a bit faster at each recursive step it chooses (one of) the group(s) with the fewest number of positions to fill out. It runs in 330ms.

```from enigma import printf

# suppose the layers of the cube are:
#
# 00 01 02   N
# 03 04 05  W E  top
# 06 07 08   S
#
# 09 10 11   N
# 12 13 14  W E  middle
# 15 16 17   S
#
# 18 19 20   N
# 21 22 23  W E  bottom
# 24 25 26   S

# then the groups we are interested in are:
groups = (
# vertical columns (top to bottom)
(0, 9, 18), (1, 10, 19), (2, 11, 20),
(3, 12, 21), (4, 13, 22), (5, 14, 23),
(6, 15, 24), (7, 16, 25), (8, 17, 26),
# horizontal rows (west to east)
(0, 1, 2), (3, 4, 5), (6, 7, 8),
(9, 10, 11), (12, 13, 14), (15, 16, 17),
(18, 19, 20), (21, 22, 23), (24, 25, 26),
# horizontal rows (north to south)
(0, 3, 6), (1, 4, 7), (2, 5, 8),
(9, 12, 15), (10, 13, 16), (11, 14, 17),
(18, 21, 24), (19, 22, 25), (20, 23, 26),
)

# the words we are given
words = list('acb aeb afd bae baf bcd bce bde bec cbe cda cef cfe daf dba dca dea dfe ebc ebd edc efa efb efd fab feb fec'.split(' '))

# remove an element from a list, and return a new list
def remove(x, v):
x = list(x)
x.remove(v)
return x

# assign <words> to <groups> in <cube>
def solve(cube, groups, words):
# are we done?
if not words:
printf("[{cube}]", cube=' '.join(cube))
# the answers we want are the groups that include the centre block (13)
groups = ((4, 13, 22), (12, 13, 14), (10, 13, 16))
print(' / '.join(sorted(''.join(cube[i] for i in g) for g in groups)))
else:
# find the most filled out group
gs = list()
for g in groups:
filled = list(cube[i] for i in g)
gs.append((g, filled, filled.count(None)))
g = min(gs, key=lambda x: x[2])
# and assign a word to it
for w in words:
if all(x is None or x == y for (x, y) in zip(g[1], w)):
cube2 = list(cube)
for (i, v) in zip(g[0], w):
cube2[i] = v
# and solve for the remaining groups and words
solve(cube2, remove(groups, g[0]), remove(words, w))