Enigmatic Code

Programming Enigma Puzzles

Enigma 1657: Magically different

From New Scientist #2823, 30th July 2011 [link]

The magic square shown is different. When complete, it contains all the numbers 1 to 36, and any six of them (no two in the same row or in the same column) add up to the same total.

What are the numbers behind the letters ENIGMA?

[enigma1657]

Advertisements

One response to “Enigma 1657: Magically different

  1. jimrandell 4 December 2011 at 2:07 pm

    This Python program is adapted from an algorithm I wrote to strategically solve Sudoku puzzles. It runs in 34ms.

    import copy
    
    class Impossible(Exception): pass
    class Solved(Exception): pass
    
    class Puzzle:
    
      def __init__(self, grid):
        self.grid = grid
        self.numbers = set(range(1, 37))
        for r in self.grid:
          self.numbers.difference_update(r)
    
      def clone(self):
        return copy.deepcopy(self)
    
      def become(self, other):
        for x in vars(other).keys():
          setattr(self, x, getattr(other, x))
    
      def place(self, r, c, n):
        if not n in self.numbers: raise Impossible
        self.numbers.remove(n)
        self.grid[r][c] = n
        if len(self.numbers) == 0: raise Solved
    
      def complete(self):
        n = len(self.numbers)
        for c1 in range(0, 5):
          for c2 in range(c1 + 1, 6):
            for r1 in range(0, 5):
              for r2 in range(r1 + 1, 6):
                a = self.grid[r1][c1]
                b = self.grid[r1][c2]
                c = self.grid[r2][c1]
                d = self.grid[r2][c2]
                if a == 0 and b > 0 and c > 0 and d > 0:
                  self.place(r1, c1, b + c - d)
                elif b == 0 and a > 0 and c > 0 and d > 0:
                  self.place(r1, c2, a + d - c)
                elif c == 0 and a > 0 and b > 0 and d > 0:
                  self.place(r2, c1, a + d - b)
                elif d == 0 and a > 0 and b > 0 and c > 0:
                  self.place(r2, c2, b + c - a)
        return len(self.numbers) < n
    
      def hypothetical(self):
        for c in range(0, 6):
          for r in range(0, 6):
            if self.grid[r][c]: continue
            for n in self.numbers:
              new = self.clone()
              new.place(r, c, n)
              if new.solve():
                self.become(new)
                return True
            raise Impossible
        return False
    
      def _solve(self, strategy):
        while len(self.numbers) > 0:
          while strategy[0](): pass
          for s in strategy[1:]:
            if s(): break
    
      def solve(self):
        try:
          self._solve([self.complete, self.hypothetical])
        except(Impossible, Solved):
          pass
        return len(self.numbers) == 0
    
    
    grid = [
      [  0,  0,  0,  0,  0,  0 ],
      [  0, 22,  0,  0, 19,  0 ],
      [  0,  0, 15, 18,  0,  0 ],
      [  0, 24,  0, 36,  0,  0 ],
      [  0,  0,  0,  0,  1,  0 ],
      [ 29,  0,  0,  0, 20,  0 ]
    ]
    
    p = Puzzle(grid)
    if p.solve():
      for r in p.grid:
        for n in r:
          print(" {:2d}".format(n), end='')
        print("")
      print("E N I G M A =", ' '.join(map(str, p.grid[0])))
    

    Solution: E=11, N=5, I=14, G=17, M=2, A=8.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: