Enigmatic Code

Programming Enigma Puzzles

Enigma 1278: Natural numbers

From New Scientist #2436, 28th February 2004

I have assigned a number to each letter of the alphabet. The numbers, which are not all different, include negative numbers, zero, positive numbers and fractions. I can tell you that:

O + N + E = 1
T + W + O = 2
T + H + R + E + E = 3
F + O + U + R = 4
F + I + V + E = 5
S + I + X = 6
S + E + V + E + N = 7
E + I + G + H + T = 8
N + I + N + E = 9
T + E + N = 10
E + L + E + V + E + N = 11
T + W + E + L + V + E = 12
T + H + I + R + T + E + E + N = 13
F + O + U + R + T + E + E + N = 14

Find the value of  (A + F + F + I + X + I + N + G) – (A + N + S + W + E + R).

[enigma1278]

Advertisements

5 responses to “Enigma 1278: Natural numbers

  1. Jim Randell 15 November 2014 at 9:24 am

    This is the puzzle that inspired Enigma 1292. Not surprisingly the same kind of programming approach works on it.

    This Python program uses the SymPy library to deal with the simultaneous equations. It runs in 450ms.

    from sympy import symbols, Eq, solve
    from enigma import printf
    
    (O, N, E, T, W, H, R, F, U, I, V, S, X, G, L, A) = symbols(tuple('ONETWHRFUIVSXGLA'))
    
    eqs = (
      Eq(O + N + E, 1),
      Eq(T + W + O, 2),
      Eq(T + H + R + E + E, 3),
      Eq(F + O + U + R, 4),
      Eq(F + I + V + E, 5),
      Eq(S + I + X, 6),
      Eq(S + E + V + E + N, 7),
      Eq(E + I + G + H + T, 8),
      Eq(N + I + N + E, 9),
      Eq(T + E + N, 10),
      Eq(E + L + E + V + E + N, 11),
      Eq(T + W + E + L + V + E, 12),
      Eq(T + H + I + R + T + E + E + N, 13),
      Eq(F + O + U + R + T + E + E + N, 14),
    )
    
    def sums(s, xs):
      r = 0
      for x in xs:
        v = s.get(x, x)
        printf("[{x} = {v}]")
        r += v
      printf("[{xs} = {r}]", xs=' + '.join(str(x) for x in xs))
      return r
    
    for s in solve(eqs, dict=True):
      a = sums(s, (A, F, F, I, X, I, N, G))
      b = sums(s, (A, N, S, W, E, R))
      r = a - b
      printf("(A + F + F + I + X + I + N + G) - (A + N + S + W + E + R) = {r}")
    

    Solution: (A + F + F + I + X + I + N + G) – (A + N + S + W + E + R) = 16.

    Obviously we could get the same result from calculating (2F + 2I + X + G) – (S + W + E + R).

  2. Jim Randell 16 November 2014 at 12:58 pm

    If we consider finding the multipliers for each equation such that by summing each equation multiplied by its respective multiplier we are left with the correct coefficients of each letter then we can consider the puzzle as an LP problem.

    Here’s my GLPK model for the problem. (I’ve also tried to use PyMathProg to create the model without having to work out the data by hand, but it’s not working for me so far).

    /* run with: glpsol -m enigma1278.mod -o enigma1278.sol */
    /* or: lp_solve -rxli xli_MathProg enigma1278.mod */
    
    /* sets - label the equations and the letters */
    set EQS;
    set LETTERS;
    
    /* parameters */
    /* - count of the letters in each equation */
    param n { i in EQS, j in LETTERS };
    /* - target count of letters */
    param t { j in LETTERS };
    
    /* variables - a multiplier for each equation */
    var x { i in EQS };
    
    /* constraints - one for each letter */
    s.t. letter{ j in LETTERS }: sum{ i in EQS } x[i] * n[i, j] = t[j];
    
    data;
    
    /* the equations */
    set EQS := 1 2 3 4 5 6 7 8 9 10 11 12 13 14;
    
    /* the letters */
    set LETTERS := E F G H I L N O R S T U V W X;
    
    /* count the letters in each equation */
    param n:  E  F  G  H  I  L  N  O  R  S  T  U  V  W  X :=
          1   1  0  0  0  0  0  1  1  0  0  0  0  0  0  0
          2   0  0  0  0  0  0  0  1  0  0  1  0  0  1  0
          3   2  0  0  1  0  0  0  0  1  0  1  0  0  0  0
          4   0  1  0  0  0  0  0  1  1  0  0  1  0  0  0
          5   1  1  0  0  1  0  0  0  0  0  0  0  1  0  0
          6   0  0  0  0  1  0  0  0  0  1  0  0  0  0  1
          7   2  0  0  0  0  0  1  0  0  1  0  0  1  0  0
          8   1  0  1  1  1  0  0  0  0  0  1  0  0  0  0
          9   1  0  0  0  1  0  2  0  0  0  0  0  0  0  0
         10   1  0  0  0  0  0  1  0  0  0  1  0  0  0  0
         11   3  0  0  0  0  1  1  0  0  0  0  0  1  0  0
         12   2  0  0  0  0  1  0  0  0  0  1  0  1  1  0
         13   2  0  0  1  1  0  1  0  1  0  2  0  0  0  0
         14   2  1  0  0  0  0  1  1  1  0  1  1  0  0  0;
    
    /* target equation */
    param t :=
      E -1
      F  2
      G  1
      H  0
      I  2
      L  0
      N  0
      O  0
      R -1
      S -1
      T  0
      U  0
      V  0
      W -1
      X  1;
    
    end;
    

    There are multiple solutions, but GLPK finds one set of multipliers that give the required equation:

    [1] – [2] + [3] + 2×[4] + 2×[5] + [6] – 2×[7] + [8] + 5×[10] – 2×[13] – 2×[14] = 16.

    • Jim Randell 16 November 2014 at 3:59 pm

      Aha – I found out what the problem was with my PyMathProg solution. The bounds on a float variable default to [0, ∞), and I need them to be (-∞, ∞).

      So, here’s my PyMathProg solution (it runs in 51ms):

      import pymprog
      from collections import Counter
      from enigma import printf
      
      # the equations
      eqs = {
        'ONE': 1,
        'TWO': 2,
        'THREE': 3,
        'FOUR': 4,
        'FIVE': 5,
        'SIX': 6,
        'SEVEN': 7,
        'EIGHT': 8,
        'NINE': 9,
        'TEN': 10,
        'ELEVEN': 11,
        'TWELVE': 12,
        'THIRTEEN': 13,
        'FOURTEEN': 14,
      }
      
      # labels for the equations (in a sensible order)
      KEYS = sorted(eqs.keys(), key=lambda k: eqs[k])
      
      # count the letters in each equation
      n = dict((k, Counter(k)) for k in KEYS)
      
      # target
      t = Counter('AFFIXING')
      t.subtract('ANSWER')
      
      # create the model
      p = pymprog.model('enigma1278')
      
      # find a multiplier for each equation
      x = p.var(KEYS, 'x', float, bounds=(None, None))
      
      # constraints (one for each letter)
      for k in sorted(set().union(*KEYS)):
        printf("[letter = {k}, target = {t}]", t=t[k])
        p.st(sum(x[i] * n[i][k] for i in KEYS) == t[k])
      
      # solve the problem
      p.solve(float)
      printf("[solver status = {s}]", s=p.status())
      
      # output the answers
      r = 0
      for k in KEYS:
        m = float(x[k].primal)
        v = eqs[k]
        printf("[equation: {k} = {v}, multiplier = {m}]")
        r += m * v
      printf("result = {r}")
      

      The multipliers it finds are:

      [3] + 2×[4] + 2×[5] + [6] – 2×[7] + [8] + 5×[10] + [11] – [12] – 2×[13] – 2×[14] = 16.

      So while the GLPK solver made (E + N) – (T + W) from (O + N + E) – (T + W + O), the PyMathProg solution made it from (E + L + E + V + E + N) – (T + W + E + L + V + E).

  3. Hugh Casement 21 November 2014 at 5:33 pm

    I fear you’ve lost me with your multipliers.

    At first sight we have 14 equations in 15 unknowns, but it’s worse than that because they’re not all independent equations. FOUR = 4 and FOURTEEN = 14, so TEEN = 10; but TEN = 10 so E = 0.
    That’s reduced the number of unknowns but we have to throw out equation 14.
    Now THR = 3 and THIR = 3, so I = 0. Equation 13 is out.
    Continuing such reasoning, I deduce N = 4.5, O = -3.5, T = 5.5, W = 0.
    But after that we have only pairs or more:
    HR = -2.5, FUR = 7.5, FV = 5, SX = 6, SV = 2.5, GH = 2.5, LV = 6.5, .
    It doesn’t seem to be enough to work out 2F + X + G – (S + R).
    Have I missed something glaringly obvious?

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: