# Enigmatic Code

Programming Enigma Puzzles

## Enigma 323: A man of letters

From New Scientist #1471, 29th August 1985 [link]

Professor D. O’Phantus does all his calculations in code, with each digit represented by a letter of the alphabet. Each letter always stands for the same digit and each digit is always represented by the same letter. At the end of one of his confusing lectures on “Letter Theory” some examples of calculation remained on the blackboard.

According to the professor:

had been wiped out, but when it was multiplied by the result of the previous sum it apparently yielded OMTTOUI.

“This is quite hopeless”, said Magnus Swottus. “How can we do lots of lovely homework if we don’t know what the letters stand for? It might as well be Greek.”

But Goody-Goody Major, unwilling to be done out of his homework, was more philosophical. “We’ll just have to crack old Doodah’s code, and then just think of all the problems open to us? We’ll even be able to invent our own!”

Can you help these young enthusiasts by writing out in order the letters corresponding to the digits from 0 to 9?

[enigma323]

### 7 responses to “Enigma 323: A man of letters”

1. Jim Randell 11 December 2015 at 9:17 am

This Python program starts by using the [[ `SubstitutedSum()` ]] solver from the enigma.py library to solve the first sum. It runs in 49ms.

```from itertools import combinations
from enigma import irange, SubstitutedSum, diff, join, printf

# possible (non-zero) digits
digits = set(irange(1, 9))

# solve the sum given
p = SubstitutedSum(['CUT', 'UTC', 'TCU'], 'MEDS')
for r in p.solve():
MEDS = int(p.substitute(r, p.result))

# choose I, O, R from the remaining (non-zero) digits
for ds in combinations(digits.difference(r.values()), 3):
# the total of the second sum is: 111 * (O + I + R)
t = 111 * sum(ds)
# the product of the results
m = str(MEDS * t)
# it should be OMTTOUI
if len(m) != 7: continue
# check the letters from the first sum
if m[1:4] + m[5] != p.substitute(r, 'MTTU'): continue
# determine O, I, R
if m[0] != m[4]: continue
(O, I) = (int(m[0]), int(m[6]))
R = diff(ds, [O, I])
if len(R) > 1: continue
R = R[0]
# map digits to letters
d = { O: 'O', I: 'I', R: 'R' }
d.update((v, k) for (k, v) in r.items())

# output the solution (letters in numerical order)
printf("{d}", d=join(d.get(i, '?') for i in irange(0, 9)))
```

Solution: The letters corresponding to the digits 0 to 9 are (in order) DEMOCRITUS.

The missing result in the second addition sum would be ERRC.

• Jim Randell 11 December 2015 at 9:51 am

And here’s a version which starts from the result of the multiplication sum. It runs in 36ms.

```from enigma import irange, split, join, printf

digits = set(irange(0, 9))

# OMTTOUI is a 7-digit multiple of 111 * 111 = 12321
for i in irange(100, 801):
OMTTOUI = 12321 * i
(O, M, T, T1, O1, U, I) = split(OMTTOUI, int)
if not(O == O1 and T == T1): continue
ds1 = set((O, M, T, U, I))
if len(ds1) != 5: continue

# choose C
for C in digits.difference(ds1):
# the result of sum 1 is MEDS
MEDS = 111 * (C + U + T)
s = str(MEDS)
if len(s) != 4: continue
(M2, E, D, S) = split(s, int)
if not(M == M2): continue
ds2 = ds1.union((C, E, D, S))
if len(ds2) != 9: continue

# the remaining letter is R
R = digits.difference(ds2).pop()
# the result of sum 2 is ...
t = 111 * (R + I + O)
if t * MEDS != OMTTOUI: continue

# map digits to letters
d = dict(zip((O, M, T, U, I, C, E, D, S, R), 'OMTUICEDSR'))
printf("{d}", d=join(d[i] for i in irange(0, 9)))
```
• Jim Randell 9 September 2016 at 11:19 am

This solution uses the [[ `SubstitutedExpression()` ]] solver from the enigma.py library to solve the Alphametics. We then do a bit of manipulation of the solution to produce the output in the required format. Overall run time is 42ms.

```from enigma import SubstitutedExpression, irange, join, printf

# a solver for the alphametics
p = SubstitutedExpression([
"CUT + UTC + TCU = MEDS",
"(RIO + IOR + ORI) * MEDS = OMTTOUI"
])

# solve the alphametics
for s in p.solve():
# map digits to letters
d = dict((v, k) for (k, v) in s.items())
# output the letters in order of digits
printf("anwser = {d}", d=join(d.get(k, '?') for k in irange(0, 9)))
```
2. geoffrounce 11 December 2015 at 11:28 am

Jim, My program in MiniZinc confirms your answer. However, I had to use your sequence of letters as I was unsure about sorting the output in MiniZinc to give the required order.

```include "globals.mzn";

var 0..9:C;   var 0..9:U;  var 0..9:T;
var 0..9:R;   var 0..9:I;  var 0..9:O;
var 0..9:M;   var 0..9:E;  var 0..9:D;
var 0..9:S;

constraint
alldifferent([C,U,T,R,I,O,M,E,D,S]);

constraint
C != 0 /\ U != 0 /\ T != 0 /\ R != 0 /\I != 0 /\ M!= 0;

constraint
111 * (C + U + T) == S + 10*D + 100*E + 1000*M;

constraint
111 * (R + I + O) * (S + 10*D + 100*E + 1000*M) ==
I + 10*U + 100*O + 1000*T + 10000*T + 100000*M + 1000000*O;

solve satisfy;

% confirm Jim's sequence of letters
output [show(D),show(E),show(M),show(O),show(C),
show(R),show(I),show(T),show(U),show(S)];

% Output: 0123456789

```
3. geoffrounce 13 December 2015 at 12:37 pm

A Python 3 permutation solution:

```from itertools import permutations
digits = set('1234567890')

# construct 3 CUT numbers
for (c,u,t) in permutations(digits,3):
if c == '0' or u == '0' or t == '0': continue
cut, utc, tcu = int(c + u + t), int(u + t + c), int(t + c + u)

#construct MEDS number
for (m,e,d,s) in permutations(digits.difference(set((c,u,t))),4):
if m == 0: continue
meds = int(m + e + d + s)
if cut + utc + tcu == meds:

#construct 3 RIO numbers
for (r,i,o) in permutations(digits.difference(set((c,u,t,m,e,d,s))),3):
if r == '0' or i == '0' or o == '0': continue
rio, ior, ori = int(r + i + o), int(i + o + r), int(o + r + i)

#construct OMTTOUI
omttoui = int(o + m + t + t + o + u + i)
if (rio + ior + ori) * meds == omttoui:
dgts = (c, u, t, o, r, i, m, e, d, s)
d2l = dict(zip(dgts, 'cutorimeds'))
letters = ''.join(d2l[x] for x in sorted(d2l))
ans = letters.upper()
print('Letters corresponding to digits 0 to 9 : ',ans)

# Letters corresponding to digits 0 to 9 :  DEMOCRITUS
```
• geoffrounce 31 December 2015 at 11:18 am

A solution in a different programming language- started learning some Fortran 95 recently. Managed to confirm the answer, but printing out only the letters proved too difficult – it does not seem to have the same programming facilities as Python – not sure about later versions of Fortran. I understand Fortran has been going since 1957!

``` PROGRAM  Enigma_323_Man_of_Letters
IMPLICIT  NONE
INTEGER :: C,U,T,R,I,O,M,E,D,S     ! the digits
INTEGER :: MEDS, OMTTOUI          ! the constructed values

DO C = 1, 9
DO U = 0, 9
IF (U == C) CYCLE
DO T = 1, 9
IF (T == U .OR. T == C) CYCLE
DO R = 1, 9
IF (R == T .OR. R == U .OR. R == C) CYCLE
DO I = 1, 9
IF (I == R .OR. I == T .OR. I == U .OR.            &
I == C)  CYCLE
DO O = 1, 9
IF (O == I .OR. O == R .OR. O == T .OR.          &
O == U .OR. O == C)  CYCLE
DO M = 1, 9
IF (M == O .OR. M == I .OR. M == R .OR.        &
M == T .OR. M == U .OR. M == C)  CYCLE
DO E = 0, 9
IF (E == M .OR. E == O .OR. E == I .OR.      &
E == R .OR. E == T .OR. E == U .OR.      &
E == C)  CYCLE
DO D = 0, 9
IF (D == E .OR. D == M .OR. D == O .OR.      &
D == I .OR. D == R .OR. D == T .OR.      &
D == U .OR. D == C)  CYCLE
DO S = 0, 9
IF (S == D .OR. S == E .OR. S == M .OR.      &
S == I .OR. S == O .OR. S == R .OR.      &
S == T .OR. S == U .OR. S == C ) CYCLE

MEDS = 1000*M + 100*E + 10*D + S
OMTTOUI = 1000000*O + 100000*M + 11000*T + &
100*O + 10*U + I

IF (111 * (C + U + T) == MEDS .AND. 111 * &
(R + I + O) * MEDS == OMTTOUI) THEN
WRITE(*,"(10I2)") D,E,M,O,C,R,I,T,U,S
! Output: 0 1 2 3 4 5 6 7 8 9
END IF
END DO !S Loop
END DO ! D Loop
END DO ! E Loop
END DO ! M Loop
END DO ! O Loop
END DO ! I Loop
END DO ! R Loop
END DO ! T Loop
END DO ! U Loop
END DO ! C Loop

END PROGRAM  Enigma_323_Man_of_Letters

```
• Jim Randell 1 January 2016 at 10:04 am

I’ve not really used Fortran (my brother used it at University, but I was using BASIC at the time), but I found I had the GNU Fortran 95 compiler installed on my Raspberry Pi, so I was able to compile and run the program you posted.

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