# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1106: Not a square unused

From New Scientist #2262, 28th October 2000

Harry, Tom and I each found a set consisting of a 4-digit perfect square, a 3-digit perfect square and a 2-digit perfect square that between them used nine different digits; but none of us could add a 1-digit square with the unused digit because 9, 4, 1 and 0 all appeared in each of our three sets. No two of us found exactly the same set; none of the squares in my set appeared in either Harry’s set or Tom’s set. There is one further set that none of us found whose unused digit is again not itself a perfect square.

List in ascending order the three squares in this set that none of us found.

[enigma1106]

### 2 responses to “Enigma 1106: Not a square unused”

1. Jim Randell 17 July 2017 at 8:23 am

This Python program uses the SubstitutedExpression() solver from the enigma.py library to solve the embedded problem and find possible sets that satisfy the conditions Tom, Dick and Harry are looking for, and then examines which arrangement of possible solutions satisfies the remaining conditions. It runs in 86ms.

```from itertools import combinations
from enigma import irange, is_duplicate, SubstitutedExpression, diff, printf

# 2, 3, 4 digit squares without duplicated digits
squares = list(s for s in (i * i for i in irange(4, 99)) if not is_duplicate(s))

# find 10 digit solutions to the problem
p = SubstitutedExpression(
[ "A not in (0, 1, 4, 9)", "BC in squares", "DEF in squares", "GHIJ in squares" ],
env={ 'squares': squares }, # incorporate the list of squares into the environment
template="[unused = A, squares = (BC, DEF, GHIJ)]", # solution template
verbose=4, # output the solutions
solution="", # but don't output the substitution map
)

# record the potential answer sets
ss = list(ans for (s, ans) in p.solve())

# check answers have no squares in common
def check(s, t):
return all(a != b for (a, b) in zip(s, t))

# choose a set for me
for D in ss:
# choose sets for Harry and Tom
for (H, T) in combinations(diff(ss, [D]), 2):
# none of the squares in my set appear in H or T
if not(check(D, H) and check(D, T)): continue
# and find unused sets
for U in diff(ss, [D, T, H]):
printf("U={U} [D={D} H/T={H}/{T}]")
```

Solution: The three squares in the set none of them found were: 36, 841, 9025.

There are only 4 possible sets of squares:

[1] (16, 784, 9025) with 3 left over;
[2] (36, 841, 9025) with 7 left over;
[3] (36, 289, 5041) with 7 left over;
[4] (36, 729, 5041) with 8 left over.

Dick found set [1]. Tom and Harry found sets [3] and [4]. Leaving [2] as the set none of them found.

2. Brian Gladman 17 July 2017 at 5:21 pm
```from collections import defaultdict

# map the number of digits (2, 3 or 4) to a dictionary of
# squares with this number of different digits (the keys)
# and then to the set of digits in the square (as values)
sqrs = defaultdict(dict)
for n in range(4, 100):
sq = n * n
ss = str(sq)
dgts = set(ss)
n_dgts = len(dgts)
if n_dgts == len(ss):
sqrs[n_dgts][sq] = dgts

# create sets of triples of 2, 3 and 4 digit squares with nine
# different digits amoung them and the tenth digit not square
tr_set = set()
# two digit squares and their digit sets
for sq2, st2 in sqrs[2].items():
# three digit squares and their digit sets
for sq3, st3 in sqrs[3].items():
# their digits must be different
if not (st2 & st3):
s23 = st2 | st3
# four digit squares and their digit sets
for sq4, st4 in sqrs[4].items():
# all nine digits must be different
if not s23 & st4:
# all digits that are square must be present
if set('0149') < s23 | st4:

# we are told that there are four such triples
assert len(tr_set) == 4

# pick a triple for me
for my_tr in tr_set:
# those triples remaining
rest = tr_set.difference([my_tr])
# look for two triples that don't share any values with mine
th_trp = {s for s in rest if not (s & my_tr)}
if len(th_trp) == 2:
f = lambda x: tuple(sorted(x))
tt, ht = (f(x) for x in th_trp)
# find the fourth triple
ex, = rest.difference(th_trp)
print(f'Mine: {f(my_tr)}, [Tom, Harry]: [{tt}, {ht}], Other: {f(ex)}')
```