# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1627: A riddle for the sphinx

From New Scientist #2792, 25th December 2010 [link]

Those with a classical education will know that the sphinx was a riddle-setting monster associated with the Greek city of Thebes. I took the sum

ETA + BETA + THETA = DELTA

and replaced letters consistently with digits. Even if I told you the value of B, you still could not find all the digits, but if in addition I told you that PSI and PHI were prime, you could.

Find THEBES.

[enigma1627]

### 4 responses to “Enigma 1627: A riddle for the sphinx”

1. jimrandell 14 December 2011 at 11:56 am

This Python program runs in 65ms.

I have another version that runs in 34ms that does more early rejection based on the fact 3×A must end in A, and 3×TA must end in TA, but it’s a much longer program. In fact, it’s pretty obvious what A and T must be given this constraint, and if you modify this program to start with those values for A and T it only takes 32ms to run.

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

d = set(range(10))
for (E, T, A, B, H) in permutations(d, 5):
TA = 10*T + A
ETA = 100*E + TA
BETA = 1000*B + ETA
THETA = 10000*T + 1000*H + ETA
DELTA = ETA + BETA + THETA
if not(DELTA % 100 == TA): continue
s = str(DELTA)
if len(s) != 5: continue
if not(int(s[-4]) == E): continue
D = int(s[-5])
L = int(s[-3])

d1 = d.difference((E, T, A, B, H, D, L))
if len(d) - len(d1) != 7: continue
for (S, I, P) in permutations(d1, 3):
PSI = 100*P + 10*S + I
if not is_prime(PSI): continue
PHI = 100*P + 10*H + I
if not is_prime(PHI): continue

THEBES = 100000*T + 10000*H + 1010*E + 100*B + S

printf("ETA={ETA} BETA={BETA} THETA={THETA} DELTA={DELTA} A={A} T={T} E={E} L={L} B={B} H={H} D={D}")
printf("THEBES={THEBES} PSI={PSI} PHI={PHI} S={S} I={I} P={P}")
```

Solution: THEBES = 542823.

2. Jim Randell 8 January 2013 at 3:27 pm

Here’s a solution that uses the [[ `SubstitutedSum()` ]] solver from the enigma.py module. Although it’s not that much shorter, but it is a little bit faster – it runs in 45ms.

```from collections import defaultdict
from itertools import permutations
from enigma import irange, is_prime, SubstitutedSum, printf

# record solutions to the sum by the value of B
r = defaultdict(list)
p = SubstitutedSum(['ETA', 'BETA', 'THETA'], 'DELTA')
for s in p.solve():
r[s['B']].append(s)

# consider non-unique solutions for B
ds = set(irange(0, 9))
for (k, v) in r.items():
if len(v) < 2: continue
for s in v:
# the remaining digits are P, S, I
for x in permutations(ds.difference(s.values())):
s.update(zip('PSI', x))
PSI = p.substitute(s, 'PSI')
if not is_prime(int(PSI)): continue
PHI = p.substitute(s, 'PHI')
if not is_prime(int(PHI)): continue

THEBES = p.substitute(s, 'THEBES')
printf("{p.text} / {s}", s=p.substitute(s, p.text))
printf("THEBES={THEBES} PSI={PSI} PHI={PHI}")
```
3. geoffrounce 14 June 2018 at 8:09 am
```% A Solution in MiniZinc
include "globals.mzn";

var 0..9: E;  var 0..9: T;  var 0..9: A;  var 0..9: P;
var 0..9: S;  var 0..9: I;  var 0..9: B;  var 0..9: H;
var 0..9: D;  var 0..9: L;

constraint E > 0 /\ P > 0 /\ B > 0 /\ T > 0 /\ D > 0 ;

constraint all_different ( [E, T, A, P, S, I, B, H, D, L] );

var 100..999 : ETA = 100*E + 10*T + A;
var 100..999 : PSI = 100*P + 10*S + I;
var 100..999 : PHI = 100*P + 10*H + I;
var 1000..9999 : BETA = 1000*B + 100*E + 10*T + A;
var 10000..99999 : THETA = 10000*T + 1000*H + 100*E + 10*T + A;
var 10000..99999 : DELTA = 10000*D + 1000*E + 100*L + 10*T + A;
var 100000..999999 : THEBES = 100000*T + 10000*H + 1000*E + 100*B + 10*E + S;

predicate is_prime(var int: x) =
x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x)))))
((i < x) -> (x mod i > 0));

constraint is_prime(PSI) /\ is_prime(PHI);

constraint ETA + BETA + THETA = DELTA;

solve satisfy;

output [ "Sum is: " ++ show(ETA) ++ " + " ++ show(BETA) ++ " + "
++ show(THETA) ++  " = " ++ show(DELTA) ++ "\n"
++ "THEBES = " ++ show (THEBES) ++ "\n"
++ "PSI = " ++ show(PSI) ++ ", " ++ "PHI = " ++ show(PHI) ];

% Sum is: 250 + 8250 + 54250 = 62750
% THEBES = 542823
% PSI = 139, PHI = 149
```

@Jim: Would your filter_unique library function work OK on this Enigma ?

• Jim Randell 14 June 2018 at 11:27 pm

@geoff: Yes, you can use the [[ `filter_unique()` ]] function in a solution to this problem:

```from collections import namedtuple
from enigma import SubstitutedExpression, filter_unique, is_prime, printf

# the alphametic sum
p = SubstitutedExpression(
'ETA + BETA + THETA = DELTA',
answer="(B, (A, B, D, E, H, L, T), (PSI, PHI), THEBES)"
)

# find all solutions
S = namedtuple('S', 'B letters words answer')
ss = list(S(*ans) for (s, ans) in p.solve(verbose=1))

# "if I told you the value of B you could not find all the digits"
(_, ss) = filter_unique(ss, (lambda s: s.B), (lambda s: s.letters))

# but we only want solutions where PSI and PHI are prime
ss = filter((lambda s: all(is_prime(w) for w in s.words)), ss)

# output solutions
for s in ss:
printf("THEBES={s.answer} [(A, B, D, E, H, L, T) = {s.letters}, (PSI, PHI) = {s.words}]")
```

The strange thing is that the “even if I told you the value of B, you still could not find all the digits” part of the puzzle is superfluous. As you have found you can just write a program that ignores this part of the puzzle and instead uses the fact that PSI and PHI are prime. This “additional” fact actually narrows the possible solutions to a single candidate anyway, so you can do without line 15 and the call to [[ `filter_unique()` ]].

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