Tagged: by: W S Graff-Baker Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 8:11 am on 16 January 2026 Permalink | Reply
    Tags: by: W S Graff-Baker,   

    Teaser 2312: Backward step 

    From The Sunday Times, 14th January 2007 [link]

    Seb had just been given his four-digit PIN, and he was afraid that he would not be able to remember it. So he broke all the rules and wrote it in his pocket diary. But to make it “more secure” he did not actually write the PIN; instead, he wrote the digits in reverse order. He was surprised to discover that the new number was a multiple of the correct PIN.

    What is his PIN?

    Note that without additional requirements there are many solutions to this puzzle. The intended solution seems to come from the requirement that all the digits of the PIN are non-zero.

    [teaser2312]

     
    • Jim Randell's avatar

      Jim Randell 8:12 am on 16 January 2026 Permalink | Reply

      Here is a solution using the [[ SubstitutedExpression ]] solver from the enigma.py library.

      It runs in 82ms. (Internal runtime of the generated code is 1.7ms).

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      # suppose the real PIN is ABCD
      "ediv(DCBA, ABCD) > 1"
      "D >= A" # [optional]
      
      --distinct=""
      --invalid=""
      --digits="1-9"
      --answer="ABCD"
      

      Solution: The PIN is: 2178.

      And so the reversed PIN is: 8712.

      And: 8712 = 4 × 2178.

      (The multiple solutions to the puzzle as published can be seen by removing the digit restriction on line 11).


      Without the restriction to non-zero digits there are 131 solutions, for example (reversed-PIN, PIN):

      1000 & 0001
      1010 & 0101

      9801 & 1089

      9990 & 0999

      (Although not all these would be surprising).

      But only one of these solutions remains if the digits of the PIN must all be non-zero.


      The published solution was: “1089 or 2178”.

      Like

    • Ruud's avatar

      Ruud 10:33 am on 16 January 2026 Permalink | Reply

      import istr
      print(*(pin for digits in istr.product(range(1, 10), repeat=4) if (pin:=istr.join(digits))[::-1].divided_by(pin) not in (1, None)))
      

      Like

    • GeoffR's avatar

      GeoffR 7:43 pm on 16 January 2026 Permalink | Reply

      from enigma import nsplit, is_pairwise_distinct
      
      for pin in range(1234, 9876):
          a, b, c, d = nsplit(pin)
          if 0 in (a, b, c, d): continue
          if is_pairwise_distinct(a, b, c, d):
              rev_pin = 1000*d + 100*c + 10*b + a
              q, r = divmod(rev_pin, pin)
              if r == 0 and q > 1:
                 print(f"Pin = {pin}.")
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 9:00 am on 1 June 2023 Permalink | Reply
    Tags: by: W S Graff-Baker   

    Teaser 2108: Touch of magic 

    From The Sunday Times, 9th February 2003 [link]

    Place a single digit into each of the nine squares, such that:

    • There is no repeat in any row and no repeat in any column.
    • Each row, read in either direction, is a three-figure prime.
    • Each column, read up or down, is a three-figure prime.

    What is the sum of your nine digits?

    [teaser2108]

     
    • Jim Randell's avatar

      Jim Randell 9:01 am on 1 June 2023 Permalink | Reply

      We can use the [[ SubstitutedExpression ]] solver from the enigma.py library to solve this puzzle.

      The following run file executes in 79ms. (Internal runtime of the generated code is 11ms).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      #  A B C
      #  D E F
      #  G H I
      
      # no repeats in rows/columns
      --distinct="ABC,DEF,GHI,ADG,BEH,CFI"
      
      # rows are 3-digit primes (in either direction)
      "is_prime(ABC)" "is_prime(CBA)"
      "is_prime(DEF)" "is_prime(FED)"
      "is_prime(GHI)" "is_prime(IHG)"
      
      # columns are 3-digit primes (in either direction)
      "is_prime(ADG)" "is_prime(GDA)"
      "is_prime(BEH)" "is_prime(HEB)"
      "is_prime(CFI)" "is_prime(IFC)"
      
      # answer is the sum of the digits
      --answer="A + B + C + D + E + F + G + H + I"
      
      --template="(ABC DEF GHI)"
      --solution=""
      

      Solution: The sum of the digits is 50.

      One arrangement is:

      We also get a solution if we reverse the rows (left to right), or reverse the order of the rows (top to bottom), or both.

      Like

    • Frits's avatar

      Frits 5:19 pm on 2 June 2023 Permalink | Reply

        
      from itertools import permutations
      
      # 143 prime numbers between 100 and 1000
      P = [3, 5, 7]
      P += [x for x in range(11, 33, 2) if all(x % p for p in P)]
      P = [str(x) for x in range(101, 1000, 2) if all(x % p for p in P)]
      
      # a list of all valid prime numbers
      p_both = [p for p in P if len(set(p)) == 3 and p[::-1] in P]
      # a list of all valid prime numbers without it's reverse
      p_single = [p for p in p_both if p[0] < p[2]]
      
      
      #       2 ends  (also for middle layers)
      #      /     \
      #   +---+---+---+
      #   |   |   |   |
      #   +---+---+---+
      #   |   |   |   | <-- edge
      #   +---+---+---+
      #   |   |   |   |
      #   +---+---+---+
      #      \  |  /
      #     1 side
      
      ends = set(y for x in p_single for y in (x[0], x[2]))
      edges = set(x[1] for x in p_single if x[1] in ends)
      middle_layers = [x[::k] for x in p_single if set([x[0], x[2]]) <= edges 
                       for k in (-1, 1)]
      
      # a side of 3 cells must have an odd edge and it's edge must be an end
      sides = [x[::k] for x in p_single if x[1] in "13579" and x[1] in ends 
               for k in (-1, 1)]
      
      # pick 2 different sides for top and bottom horizontal layer
      for p in permutations(sides, 2):
        s1, s2 = p
        # vertically digits may not match
        if any(s1[i] == s2[i] for i in range(3)): continue
        # pick a horizontal middel layer
        for m in middle_layers:
          # check column for prime numbers 
          if any(s1[i] + m[i] + s2[i] not in p_both for i in range(3)): continue
          sm = sum(int(s1[i]) + int(m[i]) + int(s2[i]) for i in range(3))
          print(f"{s1}\n{m}  with sum {sm}\n{s2}\n ") 
      

      Like

    • GeoffR's avatar

      GeoffR 8:12 pm on 2 June 2023 Permalink | Reply

      # reusing first part of Frits' code
      P = [3, 5, 7]
      P += [x for x in range(11, 33, 2) if all(x % p for p in P)]
      P = [str(x) for x in range(101, 1000, 2) if all(x % p for p in P)]
      
      # a list of all valid reversed prime numbers - only 22 no.
      p_both = [str(p) for p in P if len(set(p)) == 3 and p[::-1] in P]
      
      # grid
      # a b c = prime q1 
      # d e f = prime q2 
      # g h i = prime q3 
      
      from enigma import all_different
      from itertools import permutations
      
      for p1 in permutations(p_both, 3):
          q1, q2, q3 = p1
          # find digits in L.H. column
          a, d, g =  q1[0],  q2[0],  q3[0]
          adg, gda = a + d + g, g + d + a
          if adg in p_both and gda in p_both:
              
             # find digits in middle column
             b, e, h =  q1[1], q2[1], q3[1]
             beh, heb = b + e + h, h + e + b
             if beh in p_both and heb in p_both:
                 
                 # find digits in R.H. column
                 c, f, i = q1[2], q2[2], q3[2],
                 cfi, ifc = c + f + i, i + f + c
                 if cfi in p_both and ifc in p_both:
                     # check all rows and columns are different
                     if all_different(q1, q2, q3, adg, beh, cfi):
                         print(q1); print(q2); print(q3)
                         # find total of all digits in the grid
                         total = sum(int(i) for i in (a,b,c,d,e,f,g,h,i))
                         print('Total of all digits = ', total)
                         print()
      
      # 937
      # 743
      # 179
      # Total of all digits =  50
      
      
      

      Like

      • Frits's avatar

        Frits 1:39 pm on 3 June 2023 Permalink | Reply

        or

           
        from itertools import permutations
        
        # 143 prime numbers between 100 and 1000
        P = [3, 5, 7]
        P += [x for x in range(11, 33, 2) if all(x % p for p in P)]
        P = [str(x) for x in range(101, 1000, 2) if all(x % p for p in P)]
         
        # a list of all valid prime numbers
        p_both = [p for p in P if len(set(p)) == 3 and p[::-1] in P]
         
        for p in permutations(p_both, 3):
          # transpose the permutations to get the columns
          if any(''.join(col) not in p_both for col in zip(*p)): continue
        
          print('\n'.join(p))
          print("sum = ", sum(int(y) for x in p for y in x), "\n")  
        

        Like

    • GeoffR's avatar

      GeoffR 2:56 pm on 3 June 2023 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % a b c
      % d e f 
      % g h i 
      
      % Reversible primes can only start or end  with 1,3,7 ot 9.
      set of int: pr = {1,3,7,9}; 
      
      var pr:a; var pr:b; var pr:c; 
      var pr:d; var 0..9:e; var pr:f;
      var pr:g; var pr:h; var pr:i; 
      
      % Reversible primes, as  found in the Python solution
      set of int: primes = {107, 149, 157, 167, 179, 347,
      359, 389, 701, 709, 739, 743, 751, 761, 769, 907,
      937, 941, 953, 967, 971, 983};
      
      % Reversible prime rows and columns
      constraint (100*a + 10*b + c) in primes;
      constraint (100*c + 10*b + a) in primes;
      
      constraint (100*d + 10*e + f) in primes;
      constraint (100*f + 10*e + d) in primes;
      
      constraint (100*g + 10*h + i) in primes;
      constraint (100*i + 10*h + g) in primes;
      
      constraint (100*a + 10*d + g) in primes;
      constraint (100*g + 10*d + a) in primes;
      
      constraint (100*b + 10*e + h) in primes;
      constraint (100*h + 10*e + b) in primes;
      
      constraint (100*c + 10*f + i) in primes;
      constraint (100*i + 10*f + c) in primes;
      
      % all rows and columns are different
      constraint all_different([ (100*a + 10*b + c) ,
      (100*d + 10*e + f), (100*g + 10*h + i), (100*a + 10*d + g),
      (100*b + 10*e + h), (100*c + 10*f + i)]);
      
      solve satisfy;
      
      output[ show(a), show(b),show(c) ++
      "\n" ++ show(d),show(e),show(f) ++
      "\n" ++ show(g),show(h),show(i) ++
      "\nDigit total = " ++ show(a+b+c+d+e+f+g+h+i)];
      
      
      

      Like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Design a site like this with WordPress.com
Get started