Enigmatic Code

Programming Enigma Puzzles

Enigma 1548: Easy threes

From New Scientist #2711, 6th June 2009 [link]

I started with a list of six odd numbers, all divisible by 3 (and with no leading zeros, of course). Then I coded the numbers by consistently replacing digits by letters, with different letters used for different digits. The list then became:

MAY IMAGINE MAKING EASY ENIGMA EASIER

(a) Which letter represents 6?

(b) Which digit is represented by N?

[enigma1548]

Advertisements

5 responses to “Enigma 1548: Easy threes

  1. Jim Randell 27 March 2012 at 7:15 am

    This is my original Perl version. It runs in 28ms.

    use strict;
    
    sub distinct {
      my $n = shift;
      for (@_) {
        return 0 if $n == $_;
      }
      return 1;
    }
    
    my ($M, $A, $Y, $MAY);
    my ($I, $G, $N, $E, $IMAGINE);
    my ($K, $MAKING);
    my ($S, $EASY);
    my ($ENIGMA);
    my ($R, $EASIER);
    my ($SIX);
    
    # A,Y,G,E,R end words so must be odd, i.e. 1,3,5,7,9, and there are five letters and five odd numbers,
    # so M,I,N,K,S must be even, i.e. 0,2,4,6,8, and those that begin words M,I can't be 0.
    
    for $M (2, 4, 6, 8) {
      for $A (1, 3, 5, 7, 9) {
        for $Y (1, 3, 5, 7, 9) {
          next unless distinct($Y, $A);
          $MAY = int "$M$A$Y";
          next unless $MAY % 3 == 0;
    
          for $I (2, 4, 6, 8) {
            next unless distinct($I, $M);
            for $G (1, 3, 5, 7, 9) {
              next unless distinct($G, $A, $Y);
              for $N (0, 2, 4, 6, 8) {
                next unless distinct($N, $M, $I);
                for $E (1, 3, 5, 7, 9) {
                  next unless distinct($E, $A, $Y, $G);
                  $IMAGINE = int "$I$M$A$G$I$N$E";
                  next unless $IMAGINE % 3 == 0;
    
                  for $K (0, 2, 4, 6, 8) {
                    next unless distinct($K, $M, $I, $N);
                    $MAKING = int "$M$A$K$I$N$G";
                    next unless $MAKING % 3 == 0;
    
                    for $S (0, 2, 4, 6, 8) {
                      next unless distinct($S, $M, $I, $N, $K);
                      $EASY = int "$E$A$S$Y";
                      next unless $EASY % 3 == 0;
    
                      $ENIGMA = int "$E$N$I$G$M$A";
                      next unless $ENIGMA % 3 == 0;
    
                      for $R (1, 3, 5, 7, 9) {
                        next unless distinct($R, $A, $Y, $G, $E);
                        $EASIER = int "$E$A$S$I$E$R";
                        next unless $EASIER % 3 == 0;
    
                        $SIX = ($M == 6 ? 'M' : $I == 6 ? 'I' : $N == 6 ? 'N' : $K == 6 ? 'K' : $S == 6 ? 'S' : '?');
                        print "[$SIX=6/N=$N] MAY=$MAY IMAGINE=$IMAGINE MAKING=$MAKING EASY=$EASY ENIGMA=$ENIGMA EASIER=$EASIER\n";
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    

    Solution: (a) I = 6, (b) N = 4.

    • Jim Randell 27 March 2012 at 8:32 am

      And here’s a much more compact (but slower) Python version. It uses the same observation about odd/even numbers as the Perl version, but it permutes the letters assigned to the numbers rather than vice versa. It runs in 149ms.

      from itertools import permutations
      from enigma import concat, printf
      
      words = ('MAY', 'IMAGINE', 'MAKING', 'EASY', 'ENIGMA', 'EASIER')
      
      # the words are all odd so (A, E, G, R, Y) = (1, 3, 5, 7, 9) (in some order)
      # leaving (I, K, M, N, S) = (0, 2, 4, 6, 8) (in some order)
      # and neither I nor M can be 0
      
      for evens in permutations("IKMNS"):
        if evens[0] in ("I", "M"): continue
        l2n = dict(zip(evens, (0, 2, 4, 6, 8)))
        for odds in permutations("AEGRY"):
          l2n.update(zip(odds, (1, 3, 5, 7, 9)))
          if any(n % 3 for n in (int(concat(*(l2n[l] for l in w))) for w in words)): continue
          n2l = dict((n, l) for (l, n) in l2n.items())
          printf("{six}=6 N={N} [{d}]", six=n2l[6], N=l2n['N'], d=' '.join(l+'='+str(n) for (l,n) in l2n.items()))
      
  2. Brian Gladman 27 March 2012 at 7:23 am

    The following provides a simple but slow solution that can be made much more efficient by building in more intelligence

    from __future__ import print_function
    from itertools import permutations
    
    fs = "'{0[0]:s}' represents 6, {0[1]:d} is represented by 'N'"
    words = ( 'MAY', 'IMAGINE', 'MAKING', 'EASY', 'ENIGMA', 'EASIER' )
    
    letters = set()
    for w in words:
      letters |= set(c for c in w)
    letters = tuple(letters)
    
    solutions = []
    for p in permutations(range(10)):
      d = dict(zip(letters, p))
      if (d['Y'] & d['E'] & d['G'] & d['A'] & d['R']):
        if '0' not in ''.join(str(d[c]) for c in 'EIM'):
          v = (int(''.join(str(d[c]) for c in w)) for w in words)
          if all(x % 3 == 0 for x in v):
            e = dict(zip(p, letters))
            t = (e[6], d['N'])
            if t not in solutions:
              solutions += [t]
              print(fs.format(t))
    
  3. Hugh Casement 18 February 2016 at 8:28 am

    The digit sum of each word must be a multiple of 3.  IMAGINE is an anagram of ENIGMA with an additional I.  Since I is even but not 0 it must be 6,  I don’t see any short cut for N.

    • geoffrounce 21 February 2016 at 12:29 pm
      % A solution in MiniZinc  
      
      include "globals.mzn";
      solve satisfy;
      
      var 0..9: E;  var 0..9: N; var 0..9: I; var 0..9: G; var 0..9: M;
      var 0..9: A;  var 0..9: K; var 0..9: S; var 0..9: R; var 0..9: Y;
      
      array[1..10] of var int : fd = [E,N,I,G,M,A,K,S,R,Y];
      
      constraint all_different(fd) /\ M > 0 /\ I > 0 /\ E > 0;
      
      predicate odd_div3 (var int : n) = n mod 2 == 1 /\ n mod 3 == 0;
      
      % Coded numbers MAY, IMAGINE, MAKING, EASY, ENIGMA, and EASIER must
      % all conform to the predicate to give a solution
      
      constraint odd_div3 (100*M + 10*A + Y);
      constraint odd_div3 (I*1000000 + M*100000 + A*10000 + G*1000 + I*100
       + N*10 + E);
      constraint odd_div3 (M*100000 + A*10000 + K*1000 + I*100 + N*10 + G);
      constraint odd_div3 (E*1000 + A*100 + S*10 + Y);
      constraint odd_div3 (E*100000 + N*10000 + I*1000 + G*100 + M*10 + A);
      constraint odd_div3 (E*100000 + A*10000 + S*1000 + I*100 + E*10 + R);
      
      output ["[E, N, I, G, M, A, K, S, R, Y] = " ++ show(fd)];
      
      % [E, N, I, G, M, A, K, S, R, Y] = [5, 4, 6, 3, 2, 1, 8, 0, 7, 9]
      % ----------
      % Finished in 128msec
      % so N = 4 and 6 = I
      %
      

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: