# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1123: German squares

From New Scientist #2279, 24th February 2001 [link]

In the following statement digits have been consistently replaced by capital letters, different letters being used for different digits:

VIER and NEUN are both perfect squares.

If I told you the number represented by VIER you could deduce with certainty the number represented by NEUN. Alternatively, if I told you the number represented by NEUN you could deduce with certainty the number represented by VIER.

What is the numerical value of the square root of (VIER × NEUN)?

[enigma1123]

### 3 responses to “Enigma 1123: German squares”

1. Jim Randell 20 March 2017 at 8:37 am

We can generate the 4-digit squares and look for pairs that match the alphametics VIER and NEUN ourselves, or we can use the SubstitutedExpression() solver from the enigma.py library to get a shorter program (although it does take slightly longer to run).

Once we have the pairs I use the filter_unique() function to select the sets which give the solution.

This Python program runs in 47ms.

```from enigma import SubstitutedExpression, filter_unique, is_square, unpack, printf

# use the alphametic solver to find (VIER, NEUN) pairs
p = SubstitutedExpression(
[ "is_square(VIER)", "is_square(NEUN)" ],
)

# collect (VIER, NEUN) pairs
r = list(s[1] for s in p.solve())

# functions to extract VIER and NEUN from a (VIER, NEUN) pair
vier = unpack(lambda v, n: v)
neun = unpack(lambda v, n: n)

# find pairs where VIER -> NEUN
(u1, _) = filter_unique(r, vier, neun)

# find pairs where NEUN -> VIER
(u2, _) = filter_unique(r, neun, vier)

# solution pairs are in both sets
for (v, n) in set(u1).intersection(u2):
root = is_square(v * n)
printf("root = {root} [VIER={v} NEUN={n}]")
```

Solution: The square root of (VIER × NEUN) is 7663.

VIER = 6241 = 79², NEUN = 9409 = 97².

The use of the unpack() function in lines 13-14 allows the code to work unmodified in both Python 2 or Python 3.

2. geoffrounce 20 March 2017 at 11:15 am

As different letters are used for different digits, VIER and NEUN must share the letter ‘E’

I did a Python dictionary solution, with ‘E’ as the key and the tuple (VIER, NEUN ) as the value
and looked for a single value of (VIER, NEUN ) based on the key ‘E’

```# form a list of 4-digit squares
sq = [x * x for x in range(32, 100)]

from itertools import permutations
from collections import defaultdict
d = defaultdict(list)

for p in permutations ('1234567890', 6):
v, i, e, r, n, u = p
if v == '0': continue
vier = int(v + i + e + r)
if vier in sq:
neun = int(n + e + u + n)
if n == '0': continue
if neun in sq:
# reference two squares on common letter 'E'
d[e] += [(vier, neun)]

# look for a single value of (vier,neun) in dictionary d,
# referenced by the common letter 'e'
for k,v in d.items():
if len(v) == 1:
print('VIER = {}, NEUN = {} '.format(v[0][0],v[0][1]))
VIER, NEUN = v[0][0], v[0][1]
print('Square Root of (VIER * NEUN) = {}'.format \
(int(VIER**0.5 * NEUN**0.5)))

# VIER = 6241, NEUN = 9409
# Square Root of (VIER * NEUN) = 7663
```

A full dictionary print-out of key (letter ‘E’) and values (VIER,NEUN] gives:

6 [(1369, 4624), (1369, 5625), (1764, 5625), (4761, 5625),
(7569, 1681), (7569, 4624)]

5 [(4356, 1521), (7056, 1521)]

4 [(6241, 9409)]

3. Brian Gladman 20 March 2017 at 2:31 pm
```from itertools import product
from collections import defaultdict

# four digit squares
sqrs = [str(x ** 2) for x in range(32, 100)]
# four digit squares without duplicated digits (for VIER)
vsqr = [x for x in sqrs if len(set(x)) == 4]
# four digit squares with a duplicated digit (for NEUN)
nsqr = [x for x in sqrs if len(set(x)) == 3 and x[0] == x[3]]

# map squares for VIER to those for NEUN and vice versa
v2n, n2v = defaultdict(list), defaultdict(list)
for v, n in product(vsqr, nsqr):
# they must have six different digits and share one
if len(set(v + n)) == 6 and v[2] == n[1]:
v2n[v].append(n)
n2v[n].append(v)

# remove values for VIER that don't identify NEUN and vice versa
v2n1 = set((v, nl[0]) for v, nl in v2n.items() if len(nl) == 1)
v2n2 = [(vl[0], n) for n, vl in n2v.items() if len(vl) == 1]

# look for digits for VIER and NEUN whose products are square
for v, n in set(v2n1).intersection(v2n2):
vi, ni = int(v), int(n)
rt = int((vi * ni) ** 0.5)
if rt ** 2 == vi * ni:
print(f'Square root = {rt}, VIER = {vi}, NEUN = {ni}.')
```