# Enigmatic Code

Programming Enigma Puzzles

## Tantalizer 496: Anky panky

From New Scientist #1047, 14th April 1977 [link]

Having unearthed a thriving protection racket in the nursery class, Miss Marple summoned the mothers of the six boys concerned to a friendly little chat. She settled the embarrassed ladies equidistantly round a circular table, while she herself paced about lecturing them.

The seating is what concerns us. On Pam’s right sat Mrs Fagin, mother of Yvor. Xerxes’ mum had Ulrich’s mum, Rhona, on her right and Sylvia on her left. Vince’s mum was on Pam’s left and opposite Sylvia. Willy’s mum was opposite Queenie, who sat on Mrs Armstrong’s right. Zacharia’s mother was opposite Mrs Capone. Tess sat opposite Mrs Ellis. Olive was on Mrs Diamond’s left.

Only Mrs Borgia had the guts to blame the whole thing on the school. Can you discover her first name?

[tantalizer496]

### 2 responses to “Tantalizer 496: Anky panky”

1. Jim Randell 14 December 2016 at 7:59 am

I made a CircularList() class that behaves like a list, but it’s elements are accessed mod n (where n is the length of the list). Then we don’t have to worry about wrapping around the indices ourselves, and from s[i] we can move left to s[i + 1], right to s[i − 1] and opposite to s[i + 3] (for a circular list of length 6).

This Python program considers all possible arrangements and runs in 196ms.

```from itertools import permutations
from enigma import printf

# implement a circular list
class CircularList(list):

def __getitem__(self, i):
return list.__getitem__(self, i % len(self))

# the last names
last = tuple('ABCDEF')

# the mum's first names
mums = tuple('OPQRST')

# the boy's first names
boys = tuple('UVWXYZ')

# consider possible positions for last names
for ls in permutations(last[1:]):
ls = CircularList(last[:1] + ls)

# consider possible positions for the boys's names
for bs in permutations(boys):
bs = CircularList(bs)

# "Mrs F is mother of Y"
if ls[bs.index('Y')] != 'F': continue

# "X's mum had U's mum on her right"
if bs[bs.index('X') - 1] != 'U': continue

# "Z's mother was opposite Mrs C"
if ls[bs.index('Z') + 3] != 'C': continue

# consider possible positions for the mum's names
for ms in permutations(mums):
ms = CircularList(ms)

# "On P's right sat Mrs F"
if ls[ms.index('P') - 1] != 'F': continue

# "U's mum is R"
if ms[bs.index('U')] != 'R': continue

# "X's mum had S on her left"
if ms[bs.index('X') + 1] != 'S': continue

# "V's mum was on P's left and opposite S"
if bs[ms.index('P') + 1] != 'V': continue
if bs[ms.index('S') + 3] != 'V': continue

# "W's mum was opposite Q"
if ms[bs.index('W') + 3] != 'Q': continue

# "Q sat on Mrs. A's right"
if ms[ls.index('A') - 1] != 'Q': continue

# "T sat opposite Mrs E"
if ms[ls.index('E') + 3] != 'T': continue

# "O was on Mrs. D's left"
if ms[ls.index('D') + 1] != 'O': continue

# accumulate solution as a list of (<last>, <first>, <child>)
r = list(zip(ls, ms, bs))
# and determine the first name of B
f = list(x[1] for x in r if x[0] == 'B')[0]
printf("Mrs B = {f} {r}")
```

Solution: Mrs Borgia’s first name is Queenie.

There are two arrangements that work, these are (going round the table in clockwise order, starting with Mrs Armstrong):

Rhona Armstrong, mother of Ulrich,
Tess Capone, mother of Xerxes,
Sylvia Diamond, mother of Willy,
Olive Fagin, mother of Yvor,
Pam Ellis, mother of Zacharia,
Queenie Borgia, mother of Vince.

and:

Sylvia Armstrong, mother of Zacharia,
Tess Fagin, mother of Yvor,
Pam Diamond, mother of Willy,
Olive Capone, mother of Vince,
Rhona Ellis, mother Ulrich,
Queenie Borgia, mother of Xerxes.

2. Jim Randell 14 December 2016 at 1:48 pm

And here’s a solution using a MiniZinc model.

```include "globals.mzn";

% label the positions 0 to 5

% last names
var 0..5: A;
var 0..5: B;
var 0..5: C;
var 0..5: D;
var 0..5: E;
var 0..5: F;

constraint all_different([A, B, C, D, E, F]);

% mum's first names
var 0..5: O;
var 0..5: P;
var 0..5: Q;
var 0..5: R;
var 0..5: S;
var 0..5: T;

constraint all_different([O, P, Q, R, S, T]);

% boy's first names
var 0..5: U;
var 0..5: V;
var 0..5: W;
var 0..5: X;
var 0..5: Y;
var 0..5: Z;

constraint all_different([U, V, W, X, Y, Z]);

% place Mrs A in position 1
constraint A == 1;

% "On P's right sat Mrs. F, mother of Y
constraint (F + 1) mod 6 == P;
constraint F == Y;

% "X's mum has U's mum, R, on her right and S on her left"
constraint (U + 1) mod 6 == X;
constraint U == R;
constraint (X + 1) mod 6 == S;

% "V's mum was on P's left and opposite S"
constraint (P + 1) mod 6 == V;
constraint (V + 3) mod 6 == S;

% "W's mum was opposite Q, who sat on Mrs A's right"
constraint (W + 3) mod 6 == Q;
constraint (Q + 1) mod 6 == A;

% "Z's mother was opposite Mrs C"
constraint (Z + 3) mod 6 == C;

% "T sat opposite Mrs E"
constraint (T + 3) mod 6 == E;

% "O was on Mrs D's left"
constraint (D + 1) mod 6 == O;

solve satisfy;
```

It can be run directly as a MiniZinc model, or you can using the minizinc.py wrapper to provide formatting of the solutions from Python. The following program runs in 153ms.

```from enigma import irange, printf
from minizinc import MiniZinc

# create the minizinc model
m = MiniZinc("tantalizer496.mzn")

# solve it
for s in m.solve():
# accumulate (<last>, <mum>, <boy>) by position
r = list(sorted(k for (k, v) in s.items() if v == i) for i in irange(0, 5))
# and determine the first name of B
f = list(x[1] for x in r if x[0] == 'B')[0]
printf("Mrs B = {f} {r}")
```

This site uses Akismet to reduce spam. Learn how your comment data is processed.