# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1548: Easy threes

From New Scientist #2711, 6th June 2009 [link]

I started with a list of six odd numbers, all divisible by 3 (and with no leading zeros, of course). Then I coded the numbers by consistently replacing digits by letters, with different letters used for different digits. The list then became:

MAY IMAGINE MAKING EASY ENIGMA EASIER

(a) Which letter represents 6?

(b) Which digit is represented by N?

[enigma1548]

### 5 responses to “Enigma 1548: Easy threes”

1. Jim Randell 27 March 2012 at 7:15 am

This is my original Perl version. It runs in 28ms.

```use strict;

sub distinct {
my \$n = shift;
for (@_) {
return 0 if \$n == \$_;
}
return 1;
}

my (\$M, \$A, \$Y, \$MAY);
my (\$I, \$G, \$N, \$E, \$IMAGINE);
my (\$K, \$MAKING);
my (\$S, \$EASY);
my (\$ENIGMA);
my (\$R, \$EASIER);
my (\$SIX);

# A,Y,G,E,R end words so must be odd, i.e. 1,3,5,7,9, and there are five letters and five odd numbers,
# so M,I,N,K,S must be even, i.e. 0,2,4,6,8, and those that begin words M,I can't be 0.

for \$M (2, 4, 6, 8) {
for \$A (1, 3, 5, 7, 9) {
for \$Y (1, 3, 5, 7, 9) {
next unless distinct(\$Y, \$A);
\$MAY = int "\$M\$A\$Y";
next unless \$MAY % 3 == 0;

for \$I (2, 4, 6, 8) {
next unless distinct(\$I, \$M);
for \$G (1, 3, 5, 7, 9) {
next unless distinct(\$G, \$A, \$Y);
for \$N (0, 2, 4, 6, 8) {
next unless distinct(\$N, \$M, \$I);
for \$E (1, 3, 5, 7, 9) {
next unless distinct(\$E, \$A, \$Y, \$G);
\$IMAGINE = int "\$I\$M\$A\$G\$I\$N\$E";
next unless \$IMAGINE % 3 == 0;

for \$K (0, 2, 4, 6, 8) {
next unless distinct(\$K, \$M, \$I, \$N);
\$MAKING = int "\$M\$A\$K\$I\$N\$G";
next unless \$MAKING % 3 == 0;

for \$S (0, 2, 4, 6, 8) {
next unless distinct(\$S, \$M, \$I, \$N, \$K);
\$EASY = int "\$E\$A\$S\$Y";
next unless \$EASY % 3 == 0;

\$ENIGMA = int "\$E\$N\$I\$G\$M\$A";
next unless \$ENIGMA % 3 == 0;

for \$R (1, 3, 5, 7, 9) {
next unless distinct(\$R, \$A, \$Y, \$G, \$E);
\$EASIER = int "\$E\$A\$S\$I\$E\$R";
next unless \$EASIER % 3 == 0;

\$SIX = (\$M == 6 ? 'M' : \$I == 6 ? 'I' : \$N == 6 ? 'N' : \$K == 6 ? 'K' : \$S == 6 ? 'S' : '?');
print "[\$SIX=6/N=\$N] MAY=\$MAY IMAGINE=\$IMAGINE MAKING=\$MAKING EASY=\$EASY ENIGMA=\$ENIGMA EASIER=\$EASIER\n";
}
}
}
}
}
}
}
}
}
}
```

Solution: (a) I = 6, (b) N = 4.

• Jim Randell 27 March 2012 at 8:32 am

And here’s a much more compact (but slower) Python version. It uses the same observation about odd/even numbers as the Perl version, but it permutes the letters assigned to the numbers rather than vice versa. It runs in 149ms.

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

words = ('MAY', 'IMAGINE', 'MAKING', 'EASY', 'ENIGMA', 'EASIER')

# the words are all odd so (A, E, G, R, Y) = (1, 3, 5, 7, 9) (in some order)
# leaving (I, K, M, N, S) = (0, 2, 4, 6, 8) (in some order)
# and neither I nor M can be 0

for evens in permutations("IKMNS"):
if evens[0] in ("I", "M"): continue
l2n = dict(zip(evens, (0, 2, 4, 6, 8)))
for odds in permutations("AEGRY"):
l2n.update(zip(odds, (1, 3, 5, 7, 9)))
if any(n % 3 for n in (int(concat(*(l2n[l] for l in w))) for w in words)): continue
n2l = dict((n, l) for (l, n) in l2n.items())
printf("{six}=6 N={N} [{d}]", six=n2l[6], N=l2n['N'], d=' '.join(l+'='+str(n) for (l,n) in l2n.items()))
```
2. Brian Gladman 27 March 2012 at 7:23 am

The following provides a simple but slow solution that can be made much more efficient by building in more intelligence

```from __future__ import print_function
from itertools import permutations

fs = "'{0[0]:s}' represents 6, {0[1]:d} is represented by 'N'"
words = ( 'MAY', 'IMAGINE', 'MAKING', 'EASY', 'ENIGMA', 'EASIER' )

letters = set()
for w in words:
letters |= set(c for c in w)
letters = tuple(letters)

solutions = []
for p in permutations(range(10)):
d = dict(zip(letters, p))
if (d['Y'] & d['E'] & d['G'] & d['A'] & d['R']):
if '0' not in ''.join(str(d[c]) for c in 'EIM'):
v = (int(''.join(str(d[c]) for c in w)) for w in words)
if all(x % 3 == 0 for x in v):
e = dict(zip(p, letters))
t = (e[6], d['N'])
if t not in solutions:
solutions += [t]
print(fs.format(t))
```
3. Hugh Casement 18 February 2016 at 8:28 am

The digit sum of each word must be a multiple of 3.  IMAGINE is an anagram of ENIGMA with an additional I.  Since I is even but not 0 it must be 6,  I don’t see any short cut for N.

• geoffrounce 21 February 2016 at 12:29 pm
```% A solution in MiniZinc

include "globals.mzn";
solve satisfy;

var 0..9: E;  var 0..9: N; var 0..9: I; var 0..9: G; var 0..9: M;
var 0..9: A;  var 0..9: K; var 0..9: S; var 0..9: R; var 0..9: Y;

array[1..10] of var int : fd = [E,N,I,G,M,A,K,S,R,Y];

constraint all_different(fd) /\ M > 0 /\ I > 0 /\ E > 0;

predicate odd_div3 (var int : n) = n mod 2 == 1 /\ n mod 3 == 0;

% Coded numbers MAY, IMAGINE, MAKING, EASY, ENIGMA, and EASIER must
% all conform to the predicate to give a solution

constraint odd_div3 (100*M + 10*A + Y);
constraint odd_div3 (I*1000000 + M*100000 + A*10000 + G*1000 + I*100
+ N*10 + E);
constraint odd_div3 (M*100000 + A*10000 + K*1000 + I*100 + N*10 + G);
constraint odd_div3 (E*1000 + A*100 + S*10 + Y);
constraint odd_div3 (E*100000 + N*10000 + I*1000 + G*100 + M*10 + A);
constraint odd_div3 (E*100000 + A*10000 + S*1000 + I*100 + E*10 + R);

output ["[E, N, I, G, M, A, K, S, R, Y] = " ++ show(fd)];

% [E, N, I, G, M, A, K, S, R, Y] = [5, 4, 6, 3, 2, 1, 8, 0, 7, 9]
% ----------
% Finished in 128msec
% so N = 4 and 6 = I
%
```