Enigmatic Code

Programming Enigma Puzzles

Enigma 323: A man of letters

From New Scientist #1471, 29th August 1985 [link]

Professor D. O’Phantus does all his calculations in code, with each digit represented by a letter of the alphabet. Each letter always stands for the same digit and each digit is always represented by the same letter. At the end of one of his confusing lectures on “Letter Theory” some examples of calculation remained on the blackboard.

According to the professor:

Enigma 323 - 1

Sadly, the result of another addition:

Enigma 323 - 2

had been wiped out, but when it was multiplied by the result of the previous sum it apparently yielded OMTTOUI.

“This is quite hopeless”, said Magnus Swottus. “How can we do lots of lovely homework if we don’t know what the letters stand for? It might as well be Greek.”

But Goody-Goody Major, unwilling to be done out of his homework, was more philosophical. “We’ll just have to crack old Doodah’s code, and then just think of all the problems open to us? We’ll even be able to invent our own!”

Can you help these young enthusiasts by writing out in order the letters corresponding to the digits from 0 to 9?

[enigma323]

Advertisements

7 responses to “Enigma 323: A man of letters

  1. Jim Randell 11 December 2015 at 9:17 am

    This Python program starts by using the SubstitutedSum() solver from the enigma.py library to solve the first sum. It runs in 49ms.

    from itertools import combinations
    from enigma import irange, SubstitutedSum, diff, join, printf
    
    # possible (non-zero) digits
    digits = set(irange(1, 9))
    
    # solve the sum given
    p = SubstitutedSum(['CUT', 'UTC', 'TCU'], 'MEDS')
    for r in p.solve():
      MEDS = int(p.substitute(r, p.result))
    
      # choose I, O, R from the remaining (non-zero) digits
      for ds in combinations(digits.difference(r.values()), 3):
        # the total of the second sum is: 111 * (O + I + R)
        t = 111 * sum(ds)
        # the product of the results
        m = str(MEDS * t)
        # it should be OMTTOUI
        if len(m) != 7: continue
        # check the letters from the first sum
        if m[1:4] + m[5] != p.substitute(r, 'MTTU'): continue
        # determine O, I, R
        if m[0] != m[4]: continue
        (O, I) = (int(m[0]), int(m[6]))
        R = diff(ds, [O, I])
        if len(R) > 1: continue
        R = R[0]
        # map digits to letters
        d = { O: 'O', I: 'I', R: 'R' }
        d.update((v, k) for (k, v) in r.items())
    
        # output the solution (letters in numerical order)
        printf("{d}", d=join(d.get(i, '?') for i in irange(0, 9)))
    

    Solution: The letters corresponding to the digits 0 to 9 are (in order) DEMOCRITUS.

    The missing result in the second addition sum would be ERRC.

    • Jim Randell 11 December 2015 at 9:51 am

      And here’s a version which starts from the result of the multiplication sum. It runs in 36ms.

      from enigma import irange, split, join, printf
      
      digits = set(irange(0, 9))
      
      # OMTTOUI is a 7-digit multiple of 111 * 111 = 12321
      for i in irange(100, 801):
        OMTTOUI = 12321 * i
        (O, M, T, T1, O1, U, I) = split(OMTTOUI, int)
        if not(O == O1 and T == T1): continue
        ds1 = set((O, M, T, U, I))
        if len(ds1) != 5: continue
      
        # choose C
        for C in digits.difference(ds1):
          # the result of sum 1 is MEDS
          MEDS = 111 * (C + U + T)
          s = str(MEDS)
          if len(s) != 4: continue
          (M2, E, D, S) = split(s, int)
          if not(M == M2): continue
          ds2 = ds1.union((C, E, D, S))
          if len(ds2) != 9: continue
      
          # the remaining letter is R
          R = digits.difference(ds2).pop()
          # the result of sum 2 is ...
          t = 111 * (R + I + O)
          if t * MEDS != OMTTOUI: continue
      
          # map digits to letters
          d = dict(zip((O, M, T, U, I, C, E, D, S, R), 'OMTUICEDSR'))
          printf("{d}", d=join(d[i] for i in irange(0, 9)))
      
    • Jim Randell 9 September 2016 at 11:19 am

      This solution uses the SubstitutedExpression() solver from the enigma.py library to solve the Alphametics. We then do a bit of manipulation of the solution to produce the output in the required format. Overall run time is 42ms.

      from enigma import SubstitutedExpression, irange, join, printf
      
      # a solver for the alphametics
      p = SubstitutedExpression([
        "CUT + UTC + TCU = MEDS",
        "(RIO + IOR + ORI) * MEDS = OMTTOUI"
      ])
      
      # solve the alphametics
      for s in p.solve():
        # map digits to letters
        d = dict((v, k) for (k, v) in s.items())
        # output the letters in order of digits
        printf("{d}", d=join(d[k] for k in irange(0, 9)))
      
  2. geoffrounce 11 December 2015 at 11:28 am

    Jim, My program in MiniZinc confirms your answer. However, I had to use your sequence of letters as I was unsure about sorting the output in MiniZinc to give the required order.

    include "globals.mzn";
     
    var 0..9:C;   var 0..9:U;  var 0..9:T;
    var 0..9:R;   var 0..9:I;  var 0..9:O;
    var 0..9:M;   var 0..9:E;  var 0..9:D;
    var 0..9:S;
    
    constraint 
         alldifferent([C,U,T,R,I,O,M,E,D,S]);
    
    constraint
         C != 0 /\ U != 0 /\ T != 0 /\ R != 0 /\I != 0 /\ M!= 0;
    
    constraint
         111 * (C + U + T) == S + 10*D + 100*E + 1000*M;
    
    constraint
         111 * (R + I + O) * (S + 10*D + 100*E + 1000*M) ==
         I + 10*U + 100*O + 1000*T + 10000*T + 100000*M + 1000000*O; 
         
    solve satisfy;
    
    % confirm Jim's sequence of letters
    output [show(D),show(E),show(M),show(O),show(C),
           show(R),show(I),show(T),show(U),show(S)];
    
    % Output: 0123456789
    
    
  3. geoffrounce 13 December 2015 at 12:37 pm

    A Python 3 permutation solution:

    from itertools import permutations
    digits = set('1234567890')
    
    # construct 3 CUT numbers
    for (c,u,t) in permutations(digits,3):
      if c == '0' or u == '0' or t == '0': continue
      cut, utc, tcu = int(c + u + t), int(u + t + c), int(t + c + u)
    
      #construct MEDS number
      for (m,e,d,s) in permutations(digits.difference(set((c,u,t))),4):
        if m == 0: continue
        meds = int(m + e + d + s)
        if cut + utc + tcu == meds:
            
          #construct 3 RIO numbers
          for (r,i,o) in permutations(digits.difference(set((c,u,t,m,e,d,s))),3):
            if r == '0' or i == '0' or o == '0': continue
            rio, ior, ori = int(r + i + o), int(i + o + r), int(o + r + i) 
        
            #construct OMTTOUI
            omttoui = int(o + m + t + t + o + u + i)
            if (rio + ior + ori) * meds == omttoui:
              dgts = (c, u, t, o, r, i, m, e, d, s)
              d2l = dict(zip(dgts, 'cutorimeds'))
              letters = ''.join(d2l[x] for x in sorted(d2l))
              ans = letters.upper()
              print('Letters corresponding to digits 0 to 9 : ',ans)
              
    # Letters corresponding to digits 0 to 9 :  DEMOCRITUS
    
    • geoffrounce 31 December 2015 at 11:18 am

      A solution in a different programming language- started learning some Fortran 95 recently. Managed to confirm the answer, but printing out only the letters proved too difficult – it does not seem to have the same programming facilities as Python – not sure about later versions of Fortran. I understand Fortran has been going since 1957!

       PROGRAM  Enigma_323_Man_of_Letters
         IMPLICIT  NONE
         INTEGER :: C,U,T,R,I,O,M,E,D,S     ! the digits
         INTEGER :: MEDS, OMTTOUI          ! the constructed values
      
         DO C = 1, 9
           DO U = 0, 9
             IF (U == C) CYCLE
             DO T = 1, 9
               IF (T == U .OR. T == C) CYCLE
               DO R = 1, 9
                 IF (R == T .OR. R == U .OR. R == C) CYCLE
                 DO I = 1, 9
                   IF (I == R .OR. I == T .OR. I == U .OR.            &
                       I == C)  CYCLE
                   DO O = 1, 9
                     IF (O == I .OR. O == R .OR. O == T .OR.          &
                         O == U .OR. O == C)  CYCLE
                     DO M = 1, 9
                       IF (M == O .OR. M == I .OR. M == R .OR.        &
                           M == T .OR. M == U .OR. M == C)  CYCLE
                       DO E = 0, 9
                         IF (E == M .OR. E == O .OR. E == I .OR.      &
                             E == R .OR. E == T .OR. E == U .OR.      &
                             E == C)  CYCLE
                         DO D = 0, 9
                           IF (D == E .OR. D == M .OR. D == O .OR.      &
                               D == I .OR. D == R .OR. D == T .OR.      &
                               D == U .OR. D == C)  CYCLE
                            DO S = 0, 9
                               IF (S == D .OR. S == E .OR. S == M .OR.      &
                                   S == I .OR. S == O .OR. S == R .OR.      &
                                   S == T .OR. S == U .OR. S == C ) CYCLE
                                   
                               MEDS = 1000*M + 100*E + 10*D + S
                               OMTTOUI = 1000000*O + 100000*M + 11000*T + & 
                               100*O + 10*U + I
                               
                               IF (111 * (C + U + T) == MEDS .AND. 111 * &
                                 (R + I + O) * MEDS == OMTTOUI) THEN
                                  WRITE(*,"(10I2)") D,E,M,O,C,R,I,T,U,S 
                                  ! Output: 0 1 2 3 4 5 6 7 8 9
                               END IF 
                            END DO !S Loop
                          END DO ! D Loop
                       END DO ! E Loop
                     END DO ! M Loop
                   END DO ! O Loop
                 END DO ! I Loop
               END DO ! R Loop
             END DO ! T Loop
           END DO ! U Loop
         END DO ! C Loop
         
      END PROGRAM  Enigma_323_Man_of_Letters
                    
      
      • Jim Randell 1 January 2016 at 10:04 am

        I’ve not really used Fortran (my brother used it at University, but I was using BASIC at the time), but I found I had the GNU Fortran 95 compiler installed on my Raspberry Pi, so I was able to compile and run the program you posted.

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: