Enigmatic Code

Programming Enigma Puzzles

Enigma 367: Spilt ink

From New Scientist #1516, 10th July 1986 [link]

Uncle Bungle has been making up another long division sum with letters substituted for digits, and those who know him well — as I do — will not be surprised to hear that all was not as it should be. Being rather old-fashioned he still uses ink, and being rather careless he has spilt it so that some of the letters were, I’m afraid, quite illegible. What can be read can be seen below, and I am glad to say that what is left is as it should be; that is, each letter stands for a different digit:

Enigma 367

Rewrite the complete sum with letters and blanks replaced by digits.

[enigma367]

2 responses to “Enigma 367: Spilt ink

  1. Jim Randell 21 October 2016 at 8:27 am

    We can use the [[ SubstitutedDivision() ]] solver from the enigma.py library to solve this problem in one line. Instead of writing a program to do the call we can invoke it directly from the command line. Here’s the command and its output:

    % python -m enigma SubstitutedDivision "trm?d / sm = txs" "trm - pkx = kt" "kt? - hx? = x?" "x?d - khx = ks"
    [solving trm?d / sm = txs, [('trm', 'pkx', 'kt'), ('kt?', 'hx?', 'x?'), ('x?d', 'khx', 'ks')] ...]
    20883 / 78 = 267 rem 57 [d=3 h=4 k=5 m=8 p=1 r=0 s=7 t=2 x=6] [208 - 156 = 52, 528 - 468 = 60, 603 - 546 = 57]
    

    This runs in 80ms.

    Solution: The complete sum is: 20883 / 78 = 267 remainder 57.

    enigma-367-solution

    We can also use the generalised alphametic solver ([[ SubstitutedExpression() ]]) from the enigma.py library.

    We introduce the symbols ABC to stand for the illegible letters (they are inserted as AABC, reading from top to bottom in the diagram). Which gives us the following run file:

    # solver to use
    SubstitutedExpression
    
    # solver options
    --symbols="dhkmprstxABC"
    --distinct="dhkmprstx"
    
    # the division sum
    "txs * sm + ks = trmAd"
    
    # the multiples
    "t * sm = pkx"
    "x * sm = hxB"
    "s * sm = khx"
    
    # the intermediate subtraction sums
    "trm - pkx = kt"
    "ktA - hxB = xC"
    "xCd - khx = ks"
    

    Which we can run like this to get the same solution:

    % python -m enigma -r enigma367.run
    (txs * sm + ks = trmAd) (t * sm = pkx) (x * sm = hxB) (s * sm = khx) (trm - pkx = kt) (ktA - hxB = xC) (xCd - khx = ks)
    (267 * 78 + 57 = 20883) (2 * 78 = 156) (6 * 78 = 468) (7 * 78 = 546) (208 - 156 = 52) (528 - 468 = 60) (603 - 546 = 57) / A=8 B=8 C=0 d=3 h=4 k=5 m=8 p=1 r=0 s=7 t=2 x=6
    [1 solution]
    

    This runs in 76ms.

    The [[ SubstitutedExpression() ]] solver uses a heuristic to choose the number of symbols it has to consider values for. In this case it only needs to look at s, m, and t, the values of the remaining symbols can be derived. The same approach can be used to solve the program manually (or indeed, programatically).

  2. Brian Gladman 21 October 2016 at 4:25 pm
    from itertools import permutations
    
    # allocate the symbols needed to complete the division
    for k, m, s, t, x in permutations(range(10), 5):
      
      # form the divisor, the dividend and the remainder
      sm, txs, ks = 10 * s + m, 100 * t + 10 * x + s, 10 * k + s
      
      # form and check the quotient and its digits where necessary
      trm_d = sm * txs + ks
      try:
        _t, r, _m, _1, d = (int(x) for x in str(trm_d))
      except ValueError:
        continue
      s1 = set((d, k, m, r, s, t, x))
      if _t != t or _m != m or len(s1) != 7:
        continue  
    
      # now form and check the first partial product
      pkx = sm * t
      try:
        p, _k, _x = (int(c) for c in str(pkx))
      except ValueError:
        continue
      if not (_x == x and _k == k and 0 < p < 10 and p not in s1):
        continue
      
      # check the remaining partial products
      kt_, hx_ = 100 * k + 10 * t + _1, sm * x
      x_d = 10 * (kt_ - hx_) + d
      try:
        h, _x, _ = (int(c) for c in str(hx_))
      except ValueError:
        continue
      s2 = s1.union([h, p])
      khx = 100 * k + 10 * h + x
      assert x_d - khx == ks and len(s2) == 9
      kt_, hx_ = 100 * k + 10 * t + _1, sm * x
      if hx_ // 10 != 10 * h + x:
        continue
      
      print('         {}'.format(txs))
      print('     -------')
      print('  {} ) {}'.format(sm, trm_d))
      print('       {}'.format(pkx))
      print('       ---')
      print('        {}'.format(kt_))
      print('        {}'.format(hx_))
      print('        ---')
      print('         {}'.format(x_d))
      print('         {}'.format(khx))
      print('         ---')
      print('          {}'.format(ks))
    

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

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

%d bloggers like this: