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

  • Unknown's avatar

    Jim Randell 9:01 am on 20 May 2026 Permalink | Reply
    Tags: by: W S Graff-Baker,   

    Teaser 2418: [Square park] 

    From The Sunday Times, 25th January 2009 [link]

    Our park is square, with sides of length 104 metres. In the centre is a circular garden with a diameter of 38 metres.

    When walking around the edge of the garden, I can reach a point that is a whole number of metres from the nearest corner of the park, and is also a whole number of metres from the furthest corner of the park.

    What are those two distances?

    This puzzle was originally published with no title.

    [teaser2418]

     
    • Jim Randell's avatar

      Jim Randell 9:02 am on 20 May 2026 Permalink | Reply

      We place the corners of the park at (±52, ±52), and the circle is centred on (0, 0) with a radius of 19.

      If the point on the circumference of the circle is (x, y), and the distance to the nearest corner (+52, +52) is a, and the distance to the furthest corner (−52, −52) is b, then we have the following equations:

      x² + y² = 19
      (52 − x)² + (52 − y)² = a²
      (52 + x)² + (52 + y)² = b²

      And we can eliminate x and y to get:

      a² + b² = 4 × 52² + 2 × 19² = 11538

      So we can look for two squares that sum to give the required value.

      The following Python program runs in 70ms. (Internal runtime is 51µs).

      from enigma import (
        sq, sum_of_squares, circle_intersect_circle, peek, point_dist, printf
      )
      
      S = 4 * sq(52) + 2 * sq(19)
      for (a, b) in sum_of_squares(S, 2):
        printf("a={a} b={b} [S={S}]")
      
        # find one of the intersection points
        p = peek(circle_intersect_circle(((52, 52), a), ((-52, -52), b)), default=None)
        if p is None: continue
        printf("-> p={p}")
      
        # determine distance to the corners
        for q in [(52, 52), (-52, -52), (-52, 52), (52, -52)]:
          d = point_dist(p, q)
          printf("-> dist to {q} = {d:.6f}")
        printf()
      

      Solution: The distances are 63 m and 87 m.

      However there is a problem with this answer.

      If we look at the distances to each of the corners, we find that the integer distances are not the distances to the nearest and furthest corners (at least not the nearest and furthest from (x, y)).

      (The integer distances are shown in red).

      The distances are:

      AX = 63 m
      BX = 88.92 m
      CX = 87 m
      DX = 60.26 m

      The shortest distance is DX and the longest distance is BX.

      But the puzzle can be saved if the radius of the circle is changed from 19 m to 18 m, then the integer distances are 58 m and 90 m, and these are the nearest and furthest distances:

      In this case the distances are:

      AX = 58 m
      BX = 83.16 m
      CX = 90 m
      DX = 67.44 m

      In fact for N = 52 there are solutions when R = 18, 27, 48.

      And there are solutions with integer distances that are not the nearest/furthest distances when R = 19, 26, 33, 39, 51.

      Like

  • 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).

      #! 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