Enigmatic Code

Programming Enigma Puzzles

Enigma 1555: Not a square

From New Scientist #2718, 25th July 2009 [link]

Fill each of the 12 cells with a digit so that the two four-digit numbers that you can read across, the two four-digit numbers that you can read down, the two two-digit numbers that you can read down at the sides and the two-digit number that you can read across at the bottom are all different perfect squares (with no leading zeros). Only the two-digit number that you can read across at the top is not a perfect square.

What is that two-digit number?

[enigma1555]

3 responses to “Enigma 1555: Not a square”

1. Jim Randell 6 March 2012 at 2:20 pm

The following Python program runs in 45ms.

```from itertools import permutations
from enigma import irange, split, is_distinct, printf

# the numbers are laid out in the following way:

#  AB
# CDEF
# GHIJ
#  KL

# and ADHK, BEIL, CDEF, GHIJ, CG, FJ, KL are all different square numbers
# what is AB?

# first find two digit squares (as strings)
squares2 = [str(i ** 2) for i in irange(4, 9)]

# and 4 digit squares (as strings)
squares4 = [str(i ** 2) for i in irange(32, 99)]

for (CG, FJ) in permutations(squares2, 2):
(C, G) = split(CG)
(F, J) = split(FJ)
for CDEF in (x for x in squares4 if (x[0], x[3]) == (C, F)):
(D, E) = split(CDEF[1:3])
for GHIJ in (x for x in squares4 if (x[0], x[3]) == (G, J)):
(H, I) = split(GHIJ[1:3])
for KL in squares2:
if not is_distinct(KL, CG, FJ): continue
(K, L) = split(KL)
for ADHK in (x for x in squares4 if (x[1], x[2], x[3]) == (D, H, K)):
if not is_distinct(ADHK, CDEF, GHIJ): continue
for BEIL in (x for x in squares4 if (x[1], x[2], x[3]) == (E, I, L)):
```

Solution: The two-digit number across the top is 71.

2. Jim Randell 6 September 2016 at 9:13 am

We can use the generic Alphametic solver (SubstitutedExpression()) from the enigma.py library to solve this without needing to write a program.

Here’s the command and it’s output (which is quite wide). It runs in 112ms.

```% python -m enigma SubstitutedExpression \
--distinct="" \
"is_square(BEIL)" \
"is_square(CDEF)" \
"is_square(GHIJ)" \
"is_square(CG)" \
"is_square(FJ)" \
"is_square(KL)" \
"is_pairwise_distinct(CG, FJ, KL)" \
"not is_square(AB)"
(is_square(ADHK)) (is_square(BEIL)) (is_square(CDEF)) (is_square(GHIJ)) (is_pairwise_distinct(ADHK, BEIL, CDEF, GHIJ)) (is_square(CG)) (is_square(FJ)) (is_square(KL)) (is_pairwise_distinct(CG, FJ, KL)) (not is_square(AB))
(is_square(7396)) (is_square(1024)) (is_square(2304)) (is_square(5929)) (is_pairwise_distinct(7396, 1024, 2304, 5929)) (is_square(25)) (is_square(49)) (is_square(64)) (is_pairwise_distinct(25, 49, 64)) (not is_square(71)) / A=7 B=1 C=2 D=3 E=0 F=4 G=5 H=9 I=2 J=9 K=6 L=4 / 71
AB = 71 [1 solution]
```

To make this kind of thing easier you can put all the parameters to enigma.py in a “run file” like this:

```# solver to use
SubstitutedExpression

# solver parameters
--distinct=""

# solver arguments
"is_square(BEIL)"
"is_square(CDEF)"
"is_square(GHIJ)"
"is_square(CG)"
"is_square(FJ)"
"is_square(KL)"
"is_pairwise_distinct(CG, FJ, KL)"
"not is_square(AB)"
```

In this case the file is saved as enigma1555.run.

And then we can run it using the -r (or --run) option to enigma.py, like this:

```% python -m enigma -r enigma1555.run
(is_square(ADHK)) (is_square(BEIL)) (is_square(CDEF)) (is_square(GHIJ)) (is_pairwise_distinct(ADHK, BEIL, CDEF, GHIJ)) (is_square(CG)) (is_square(FJ)) (is_square(KL)) (is_pairwise_distinct(CG, FJ, KL)) (not is_square(AB))
(is_square(7396)) (is_square(1024)) (is_square(2304)) (is_square(5929)) (is_pairwise_distinct(7396, 1024, 2304, 5929)) (is_square(25)) (is_square(49)) (is_square(64)) (is_pairwise_distinct(25, 49, 64)) (not is_square(71)) / A=7 B=1 C=2 D=3 E=0 F=4 G=5 H=9 I=2 J=9 K=6 L=4 / 71
AB = 71 [1 solution]
```

This functionality is available from the 2016-09-06 version of enigma.py.

3. geoffrounce 8 September 2016 at 9:28 am
```% A solution in MiniZinc
include "globals.mzn";

% 12 square grid variables
var 0..9: a;  var 0..9: b;  var 0..9: c;  var 0..9: d;
var 0..9: e;  var 0..9: f;  var 0..9: g;  var 0..9: h;
var 0..9: i;  var 0..9: j;  var 0..9: k;  var 0..9: l;

var 10..99 : ab;  % the non-square number

% perfect square variables
var 10..99 :kl; var 10..99 :cg; var 10..99 :fj;
var 1000..9999: cdef;  var 1000..9999: ghij;
var 1000..9999: adhk;  var 1000..9999: beil;

% construct 2-digit numbers
constraint ab = 10*a + b /\ kl = 10*k + l /\
cg = 10*c + g /\ fj = 10*f + j;

% construct 4-digit numbers
constraint cdef = 1000*c + 100*d + 10*e + f /\
ghij = 1000*g + 100*h + 10*i + j /\
adhk = 1000*a + 100*d + 10*h + k /\
beil = 1000*b + 100*e + 10*i + l /\
a > 0 /\ b > 0 /\ c> 0 /\ f > 0 /\
g > 0 /\ k > 0;

% construct sets of 2-digit and 4-digit numbers
set of int: sq2 = { x * x | x in 4..9 };
set of int: sq4 = { x * x | x in 31..99 };

% all perfect squares are different
constraint all_different([cg, fj, kl]);
constraint all_different ([cdef, ghij, adhk, beil]);

constraint cg in sq2 /\ fj in sq2 /\ kl in sq2;
constraint cdef in sq4 /\ ghij in sq4 /\ adhk in sq4 /\ beil in sq4;

% ab is not a square
constraint not exists(temp in 1..10) (temp*temp = ab);

solve satisfy;

output ["Non-square number is " ++ show(ab) ++ "\n" ++
"Numbers across : " ++ show(ab) ++ " " ++ show(cdef) ++ " "
++ show(ghij)++ " " ++ show(kl) ++ "\n"
++ "Numbers down   : " ++ show(cg) ++ " " ++ show(adhk) ++
" " ++ show(beil) ++ " " ++ show(fj)];

% Non-square number is 71
% Numbers across : 71 2304 5929 64
% Numbers down   : 25 7396 1024 49
% Finished in 78msec
```