# Enigmatic Code

Programming Enigma Puzzles

## Puzzle 1: Factory exam

From New Scientist #1052, 19th May 1977 [link]

There has been a lot of excitement recently about an examination which four of our employees — Alf, Bert, Charlie and Duggie — have been having in French and mathematics.

Now that we are in the Common Market it is important that we should move with the times and learn some French. And in a modern factory such as ours we must know about all the latest mathematical ideas.

It is interesting that Bert’s French place was a much above his mathematics place as Charlie’s mathematics place was below his French place. Alf’s place was even at both subjects, and Duggie’s place was odd at both. Bert was not top at either subject, and no one had the same place at both. There were no ties.

Find the order in both subjects.

This was the first in a series of puzzles called Puzzle set by Eric Emmet in New Scientist between May 1977 and February 1979 (when it was replaced by Enigma). As with his Enigma puzzles these seem to consist mostly of substituted sums, substituted divisions and football table problems.

[puzzle1]

### 2 responses to “Puzzle 1: Factory exam”

1. Jim Randell 7 October 2015 at 8:17 am

This Python program runs in 33ms.

```from itertools import permutations
from enigma import printf

# indices for A, B, C, D
(A, B, C, D) = (0, 1, 2, 3)

# choose placements for Maths
for M in permutations((1, 2, 3, 4)):

# "A's place was even in both subjects"
if M[A] % 2 != 0: continue

# "D's place was odd in both subjects"
if M[D] % 2 != 1: continue

# "B was not top at either subject"
if M[B] == 1: continue

# now choose the placements for French
for F in permutations((1, 2, 3, 4)):

# "A's place was even in both subjects"
if F[A] % 2 != 0: continue

# "D's place was odd in both subjects"
if F[D] % 2 != 1: continue

# "B was not top at either subject"
if F[B] == 1: continue

# "no one had the same place in both subjects"
if any(m == f for (m, f) in zip(M, F)): continue

# B's placement in French was as much above his placement in Maths
# as C's placement in Maths was _below_ his placement in French
if M[B] - F[B] != M[C] - F[C]: continue

# output the positions
for (n, i) in zip('ABCD', (A, B, C, D)):
printf("{n}: Maths = {m}, French = {f}", m=M[i], f=F[i])
printf()
```

Solution: In Mathematics: 1st = Duggie, 2nd = Alf, 3rd = Charlie, 4th = Bert. In French: 1st = Charlie, 2nd = Bert, 3rd = Duggie, 4th = Alf.

This is the published solution, and is the only solution if we assume that Bert’s placement in French was better than his placement in Maths. If we allow it to be worse (so the amount his placement in French was above his placement in Mathematics would be negative) then there is a further solution:

In Mathematics: 1st = Charlie, 2nd = Bert, 3rd = Duggie, 4th = Alf. In French: 1st = Duggie, 2nd = Alf, 3rd = Charlie, 4th = Bert.

This solution has the same positions as the published solution, but with the subjects swapped over.

2. geoffrounce 5 July 2016 at 4:49 pm

A piece of history here, mentioning the Common Market!

By setting the Configuration in MiniZinc to multiple solutions, I managed to get the two solutions mentioned by Jim, the first solution being the published solution

```% An early pre Enigma puzzle solution in MiniZinc
include "globals.mzn";

int: n = 4;    % total exam entrants
int: Alf = 1;
int: Bert = 2;
int: Charlie = 3;
int: Duggie = 4;

% Decision variables for exam results
array[1..n] of var 1..n: French;
array[1..n] of var 1..n: Maths;

constraint all_different(French) /\ all_different(Maths);

% Bert’s French place was as much above his Mathematics place
% as Charlie’s Mathematics place was below his French place.
constraint French[Bert] - Maths[Bert] =  French[Charlie] - Maths[Charlie];

% Alf's place was even in both subjects
constraint French[2] = Alf \/ French [4] == Alf;
constraint Maths[2] = Alf \/ Maths[4] == Alf;

% Duggie’s place was odd in both subjects
constraint Maths[1] == Duggie \/ Maths[3] == Duggie;
constraint French[1] == Duggie \/ French[3] == Duggie;

% Bert was not top at either subject
constraint Maths[1] != Bert /\ French[1] != Bert;

% No one had the same place in both exams
constraint forall(i in 1..n)
(
French[i] != Maths[i]
);

solve satisfy;

output ["French: " ++ show(French) ++ "\n" ++
"Maths:  " ++ show(Maths) ++ "\n"];

% if MiniZinc configuration is set for multiple solutions...
% --------Published Solution ( ie 1st, 2nd, 3rd, 4th)
% French: [3, 2, 4, 1]  ie  Charlie, Bert, Duggie, Alf
% Maths:  [4, 1, 3, 2]  ie  Duggie, Alf, Charlie, Bert
%
% ------ 2nd solution ------
% French: [4, 1, 3, 2]  ie Duggie, Alf, Charlie, Bert
% Maths:  [3, 2, 4, 1]  ie Charlie, Bert, Duggie, Alf
% ----------
% Finished in 78msec
%

```