# Enigmatic Code

Programming Enigma Puzzles

## Enigma 1690: Dolly the sheep

From New Scientist #2857, 24th March 2012 [link]

Dolly was the name given to the first cloned sheep at the UK’s Roslin Institute in 1996. The letters in the diagram represent, in some order, the numbers 1 to 16 forming a magic square where each row, column and main diagonal have the same sum. The letters of the word “clone”, and letters not within the square, have their values according to a=1, b=2 etc. but other letters within the square may or may not.

What is the sum d+o+l+l+y?

[enigma1690]

### 4 responses to “Enigma 1690: Dolly the sheep”

1. Jim Randell 21 March 2012 at 7:17 pm

I adapted my Magic Square Solver (last seen in Enigma 1682). I should probably wrap it up as a generic library.

The following Python program runs in 100ms.

```import copy
from enigma import irange, printf

# the numbers in the magic square
numbers = set(irange(1, 16))

# the magic constant
s = sum(numbers) // 4

# the magic square itself
square = [0] * 16

# the filled out squares
for c in list("clone"):
n = ord(c) - 97
square[n] = n+1

# remove the numbers that are already filled out
numbers.difference_update(square)

# magic lines
lines = (
# rows
( 0,  1,  2,  3),
( 4,  5,  6,  7),
( 8,  9, 10, 11),
(12, 13, 14, 15),
# columns
( 0,  4,  8, 12),
( 1,  5,  9, 13),
( 2,  6, 10, 14),
( 3,  7, 11, 15),
# diagonals
( 0,  5, 10, 15),
( 3,  6,  9, 12),
)

class Impossible(Exception): pass
class Solved(Exception): pass

class Puzzle:

def __init__(self, square, numbers):
self.square = square
self.numbers = numbers

def clone(self):
return copy.deepcopy(self)

def become(self, other):
for x in vars(other).keys():
setattr(self, x, getattr(other, x))

# complete missing squares
def complete(self):
if not self.numbers: raise Solved
for line in lines:
ns = tuple(self.square[i] for i in line)
if ns.count(0) != 1: continue
n = s - sum(ns)
if not n in self.numbers: raise Impossible
i = ns.index(0)
self.square[line[i]] = n
return True
return False

# make a guess at a square
def hypothetical(self):
if not self.numbers: raise Solved
i = self.square.index(0)
for n in self.numbers:
new = self.clone()
new.square[i] = n
if new.solve():
self.become(new)
return True
raise Impossible

# solve the square
def solve(self):
try:
while True:
while self.complete(): pass
self.hypothetical()
except (Impossible, Solved):
pass
return not(self.numbers)

p = Puzzle(square, numbers)
if p.solve():
for w in ("abcd", "efgh", "ijkl", "mnop"):
for i in list(w):
print("{i}={l:2d}".format(i=i, l=p.square[ord(i) - 97]), end=' ')
printf('')
dolly = list(p.square[ord(i) - 97] for i in list("doll"))
dolly.append(ord('y') - 96)
printf("dolly = {dolly}, sum = {sum}", sum=sum(dolly))
```

Solution: d+o+l+l+y = 77.

• Jim Randell 24 March 2012 at 9:24 am

I’ve folded the Magic Square solver into the enigma.py module, so if you have the latest version of the module the program becomes:

```from enigma import MagicSquare, printf

# make a 4x4 magic square
p = MagicSquare(4)

# set the initial values
for c in list("clone"):
i = ord(c) - 97
p.set(i, i + 1)

# solve the square
if p.solve():
# output the square
for w in ("abcd", "efgh", "ijkl", "mnop"):
for i in list(w):
print("[{i}={l:2d}]".format(i=i, l=p.get(ord(i) - 97)), end=' ')
print('')
# output the solution
dolly = list(p.get(ord(i) - 97) for i in list("doll"))
dolly.append(ord('y') - 96)
printf("dolly = {dolly}, sum = {sum}", sum=sum(dolly))
```
2. Naim Uygun 21 March 2012 at 10:33 pm