Enigmatic Code

Programming Enigma Puzzles

Enigma 394: Unwinding

From New Scientist #1544, 22nd January 1987 [link]

Professor Kugelbaum was unwinding at the Maths Club with a cigar after lunch when a wild-looking man burst in and introduced himself thus:

“My name is TED MARGIN. Juggling with the letters of my name one obtains both GREAT MIND and GRAND TIME. But I digress. Each letter of my name stands for one digit exactly from 1 to 9 inclusive and vice versa. And, do you know:

(A × R × M) / (A + R + M) = 2

MAD is greater than ART (though RAT is greater than either), and TED = MAR + GIN.

If, in addition, I were to tell you the digit which corresponds to M then you could deduce the one-to-one correspondence between the letters of my name and the digits 1 to 9″.

At this point a helpful butler removed the man, but Kugelbaum was amused to find that the information was quite consistent.

Write the digits 1 to 9 in the alphabetical order of the letters to which they correspond.

[enigma394]

5 responses to “Enigma 394: Unwinding

  1. Jim Randell 5 May 2017 at 8:32 am

    We can solve this puzzle using a couple of routines from the enigma.py library. First the [[ SubstitutedExpression() ]] solver is used to solve the alphametic expressions, then [[ filter_unique() ]] to find solutions that give a unique answer by the value of M.

    This Python 2 program runs in 48ms.

    from enigma import SubstitutedExpression, irange, filter_unique, printf
    
    # the alphametic puzzle
    p = SubstitutedExpression(
      [ "2 * (A + R + M) == A * R * M", "R > M", "M > A", "MAR + GIN = TED" ],
      digits=irange(1, 9),
      answer="ADEGIMNRT",
    )
    
    # find solutions with a unique value of M
    # the solve() function provides us with a sequence of (<dict>, <answer>) pairs
    # we require the answer be unique by the value of M in the dictionary
    (r, _) = filter_unique(p.solve(verbose=1), (lambda (d, a): d['M']), (lambda (d, a): a))
    
    # output solutions
    for (d, a) in r:
      printf("{p.answer} = {a}")
    

    Solution: ADEGIMNRT = 139274856.

    There are 4 further solutions where M = 3:

    ADEGIMNRT = 176243985
    ADEGIMNRT = 149273685
    ADEGIMNRT = 154623789
    ADEGIMNRT = 127653489

    The program can be adapted to run under Python 3 by using the [[ unpack() ]] function (from the enigma.py library) when constructing the functions to be passed to [[ filter_unique() ]]. Line 13 becomes:

    (r, _) = filter_unique(p.solve(verbose=1), unpack(lambda d, a: d['M']), unpack(lambda d, a: a))
    
  2. geoffrounce 5 May 2017 at 4:37 pm

    I found a MiniZinc solution by setting the configuration to multiple outputs and examining the outputs to find a unique answer with M = 4, giving the solution. Four other values with M = 3 were also found.

    % A Solution in MiniZinc
    include "globals.mzn";
    
    var 1..9:T;  var 1..9:E;  var 1..9:D;  var 1..9:M; var 1..9:A;  
    var 1..9:R;  var 1..9:G;  var 1..9:I;  var 1..9:N; 
    
    constraint alldifferent([T,E,D,M,A,R,G,I,N]);
    
    var 100..999: MAD = 100*M + 10*A + D;
    var 100..999: ART = 100*A + 10*R + T;
    var 100..999: RAT = 100*R + 10*A + T;
    var 100..999: TED = 100*T + 10*E + D;
    var 100..999: MAR = 100*M + 10*A + R;
    var 100..999: GIN = 100*G + 10*I + N;
    
    constraint (A * R * M) = 2 * (A + R + M) ;
    constraint MAD > ART;
    constraint (RAT > ART) /\ (RAT > MAD) ;
    constraint TED = MAR + GIN;
    
    solve satisfy;
    
    % show answer with letters in alphabetical order
    output [ " A, D, E, G, I, M, N, R, T = " ++ show([A, D, E, G, I, M, N, R, T]) ];
    
    % Answer is next line
    % A, D, E, G, I, M, N, R, T = [1, 3, 9, 2, 7, 4, 8, 5, 6] << M = 4 is unique
    
    % Other values for M = 3
    % A, D, E, G, I, M, N, R, T = [1, 7, 6, 2, 4, 3, 9, 8, 5]
    % A, D, E, G, I, M, N, R, T = [1, 4, 9, 2, 7, 3, 6, 8, 5]
    % A, D, E, G, I, M, N, R, T = [1, 5, 4, 6, 2, 3, 7, 8, 9]
    % A, D, E, G, I, M, N, R, T = [1, 2, 7, 6, 5, 3, 4, 8, 9]
    % Finished in 139msec
    
    
    • geoffrounce 7 May 2017 at 8:36 am

      A Python 3 permutation solution found the answer in 16 msec, with a total run-time of 95 msec.

      from itertools import permutations
      
      fstr = 'A={}, D={}, E={}, G={}, I={}, M={}, N={}, R={}, T={}'
      digits = set(range(1,10))
      
      for p1 in permutations(range(1,10),3):
          a, r, m = p1
          if a * r * m == 2 * (a + r + m):
              q = digits.difference((a, r, m))
              for p2 in permutations(q):
                  d, e, g, i, n, t = p2
                  mad, art = 100*m + 10*a + d, 100*a + 10*r + t
                  if mad <= art: continue
                  rat = 100*r + 10*a + t
                  if rat > mad and rat > art:
                      ted = 100*t + 10*e + d
                      mar, gin = 100*m + 10*a + r, 100*g +10*i + n
                      if ted == mar + gin:
                          print(fstr.format(a, d, e, g, i, m, n, r, t))
              
      # A=1, D=3, E=9, G=2, I=7, M=4, N=8, R=5, T=6   <<< the answer
      # A=1, D=2, E=7, G=6, I=5, M=3, N=4, R=8, T=9
      # A=1, D=4, E=9, G=2, I=7, M=3, N=6, R=8, T=5
      # A=1, D=5, E=4, G=6, I=2, M=3, N=7, R=8, T=9
      # A=1, D=7, E=6, G=2, I=4, M=3, N=9, R=8, T=5
      

      A Visual Basic (Visual Studio 2017) solution took a lot more coding to loop all the variables and test for different variable values. Output was to a console screen, which seemed a bit of a retro look.

      Module Module1
      
        Sub Main()
          Dim a, d, e, g, i, m, n, r, t As Integer
          Dim mad, art, rat, ted, mar, gin As Integer
      
          For a = 1 To 9
            For r = 1 To 9
              If r = a Then Continue For
              For m = 1 To 9
                If m = r Or m = a Then Continue For
                If a * r * m = 2 * (a + r + m) Then
                  For t = 1 To 9
                    If t = m Or t = r Or t = a Then Continue For
                    For d = 1 To 9
                      If d = t Or d = m Or d = r Or d = a Then Continue For
                      mad = 100 * m + 10 * a + d
                      art = 100 * a + 10 * r + t
                      If mad <= art Then Continue For
                      rat = r * 100 + 10 * a + t
                      If rat > mad And rat > art Then
                        For e = 1 To 9
                          If e = d Or e = t Or e = m Or e = r Or e = a Then Continue For
                          For g = 1 To 9
                            If g = e Or g = d Or g = t Or g = m Or g = r Or g = a Then Continue For
                            For i = 1 To 9
                              If i = g Or i = e Or i = d Or i = t Or i = m Or i = r Or i = a Then Continue For
                              For n = 1 To 9
                                If n = i Or n = g Or n = e Or n = d Or n = t Or n = m Or n = a Then Continue For
                                ted = 100 * t + 10 * e + d
                                mar = 100 * m + 10 * a + r
                                gin = 100 * g + 10 * i + n
                                If ted = mar + gin Then
                                  Console.WriteLine("a, d, e, g, i, m, n, r, t = {0} {1} {2} {3} {4} {5} {6} {7} {8} " _
                                                    , a, d, e, g, i, m, n, r, t)
                                  Console.ReadLine()    ' freeze console screen
                                End If
                              Next
                            Next
                          Next
                        Next
                      End If
                    Next
                  Next
                End If
              Next
            Next
          Next
        End Sub
      
        ' OUTPUT
        '-------
        'a, d, e, g, i, m, n, r, t = 1 3 9 2 7 4 8 5 6   <<< the answer
        'a, d, e, g, i, m, n, r, t = 1 4 9 2 7 3 6 8 5   
        'a, d, e, g, i, m, n, r, t = 1 7 6 2 4 3 9 8 5   
        'a, d, e, g, i, m, n, r, t = 1 2 7 6 5 3 4 8 9   
        'a, d, e, g, i, m, n, r, t = 1 5 4 6 2 3 7 8 9   
      
      End Module
      
  3. Brian Gladman 5 May 2017 at 5:53 pm
    from collections import defaultdict
    from itertools import combinations, permutations
    from functools import reduce
    
    # convert a sequence of digits to a number
    dgts2nbr = lambda *seq: reduce(lambda x, y: 10 * x + y, seq)
    
    sol = defaultdict(list)
    # start with A, M and R with A < M < R and A.R.M = 2.(A + R + M) 
    for A, R in combinations(range(1, 10), 2):
      if A * R > 2:
        M, r = divmod(2 * (A + R), A * R - 2)
        if not r and A < M < R:
          s1 = set(range(1, 10)).difference([A, R, M])
          # allocate remaining digits to remaining letters
          for D, E, G, I, N, T in permutations(s1):
            # find solutions with TED = MAR + GIN
            if dgts2nbr(T, E, D) == dgts2nbr(M, A, R) + dgts2nbr(G, I, N):
              sol[M].append((A, D, E, G, I, M, N, R, T))
    
    # look for a solution that is unique given M
    for m, t in sol.items():
      if len(t) == 1:
        print(f'(A, D, E, G, I, M, N, R, T) ==> {t[0]}')
    
  4. Jim Randell 7 May 2017 at 12:10 pm

    In an [[ itertools.permutations() ]] based approach, once we have determined values for A, M, R we don’t need to consider all 720 possible permutations of the remaining six digits for D, E, G, I, N, T, instead we can get away looking at the 120 possible values of just T, E, D (or G, I, N) and check that the values for the remaining three letters, computed from TED = MAR + GIN, consist of the remaining 3 digits.

    from itertools import permutations
    from collections import defaultdict
    from enigma import irange, nconcat, nsplit, printf
    
    ss = defaultdict(list)
    
    # A < M < R
    for A in irange(1, 7):
      for R in irange(A + 2, 9):
        d = A * R - 2
        if d < 1: continue
        (M, r) = divmod(2 * (A + R), d)
        if r != 0: continue
        if not(A < M < R): continue
    
        # choose letters for T, E, D
        MAR = nconcat(M, A, R)
        for (T, E, D) in permutations(set(irange(1, 9)).difference((A, M, R)), 3):
          TED = nconcat(T, E, D)
          # compute G, I, N
          GIN = TED - MAR
          if GIN < 123: continue
          (G, I, N) = nsplit(GIN)
          if I == 0 or N == 0: continue
          s = (A, D, E, G, I, M, N, R, T)
          if len(set(s)) != 9: continue
          # record solutions by the value of M
          printf("A={A} M={M} R={R}, T={T} E={E} D={D}, G={G} I={I} N={N}")
          ss[M].append(s)
    
    # output solutions unique by the value of M
    for (M, vs) in ss.items():
      if len(vs) == 1:
        printf("M={M} => {vs[0]}")
    

Leave a reply to Brian Gladman Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.