Enigmatic Code

Programming Enigma Puzzles

Enigma 379: Magic magic squares

From New Scientist #1528, 2nd October 1986 [link]

Enigma 379

Write, in words, different whole numbers in each of the other eight squares so that the sum of each row, column and corner-to-corner diagonal is the same. But do it in such a way that the number of letters in each of the nine squares is different and the total of letters in each row, column and corner-to-corner diagonal is the same.

What’s the highest number in the magic magic square?

[enigma379]

Advertisements

2 responses to “Enigma 379: Magic magic squares

  1. Jim Randell 13 January 2017 at 7:44 am

    This Python program runs in 37ms.

    from enigma import irange, int2words, printf
    
    #
    # consider the magic square:
    #
    #   a b c
    #   d e f
    #   g h i
    #
    
    # the central square is e=15, so the magic constant is 45 (3 * e)
    e = 15
    M = 3 * e
    
    # count the letters in numbers up to M - 3
    letters = dict((i, sum(1 for x in int2words(i) if x.isalpha())) for i in irange(1, M - 3))
    
    # let's suppose b < h
    for b in irange(1, (M - e) // 2):
      h = M - (b + e)
    
      s1 = set(letters[x] for x in (b, e, h))
      if len(s1) != 3: continue
      n1 = set((b, e, h))
    
      # let's suppose a < c
      for a in irange(1, (M - e) // 2):
        # deduce the remaining squares
        c = M - (a + b)
        i = M - (a + e)
        f = M - (c + i)
        d = M - (e + f)
        g = M - (a + d)
        # and check they are valid
        if not(g + h + i == c + e + g == M): continue
        if not all(x in letters for x in (a, c, d, f, g, i)): continue
        # and that the numbers are all different
        n2 = n1.union((a, c, d, f, g, i))
        if len(n2) != 9: continue
        # and the number of letters are all different
        s2 = s1.union(letters[x] for x in (a, c, d, f, g, i))
        if len(s2) != 9: continue
        # and the sums of the numbers of letters are the same
        L = set(sum(letters[x] for x in line)
              for line in (
                (a, b, c), (d, e, f), (g, h, i),
                (a, d, g), (b, e, h), (c, f, i),
                (a, e, i), (c, e, g)
            ))
        if len(L) == 1:
          m = max(a, b, c, d, e, f, g, h, i)
          printf("max = {m} [{a} {b} {c} / {d} {e} {f} / {g} {h} {i}]")
    

    Solution: The largest number in the square is 28.

    Here is the completed square:

    enigma-379-solution-2

    The spelled out numbers form a magic square with a magic sum of 45. The counts of the letters (in brackets) form a magic square with a magic sum of 21.

  2. Brian Gladman 13 January 2017 at 12:20 pm
    # integers less than thirty in word form
    nw = ( '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 
           'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 
           'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'twentyone', 
           'twentytwo', 'twentythree', 'twentyfour', 'twentyfive', 'twentysix',
           'twentyseven', 'twentyeight', 'twentynine' )
    
    # the length of the word forms of integers less than thirty
    ln = {i:len(x) for i, x in enumerate(nw)}
    
    # Additive magic squares have the general form:
    #
    #     e - x    e + x + y    e - y 
    #   e + x - y      e      e - x + y
    #     e + y    e - x - y    e + x
    #
    # where e is the 'magic' constant and x and y have
    # values such that 0 < x < y < e with y <> 2.x
    
    e = 15
    for y in range(1, e):
      for x in range(1, min(y, e - y)):
        if y != 2 * x:
          # the magic square
          cells = (   e - x,   e + x + y,   e - y,
                    e + x - y,     e,     e - x + y,
                      e + y,   e - x - y,   e + x   )    
          # convert this to a 'word length' square
          w, m = tuple(ln[x] for x in cells), 3 * ln[15]
          # check that all lengths are different and that
          # overall sum is correct for a magic square
          if len(set(w)) == 9 and sum(w) == 3 * m:
            # check that the 'word length' square is magic
            if all(sum(w[i] for i in ix) == m for ix in 
                   ((0, 1, 2), (3, 4, 5), (6, 7, 8),
                    (0, 3, 6), (1, 4, 7), (2, 5, 8),
                    (0, 4, 8), (2, 4, 6))):
              print(f'Highest = {max(cells)} {cells} {w}.')
    

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: