Updates from Jim Randell Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 10:20 am on 5 March 2023 Permalink | Reply
    Tags:   

    Brainteaser 1071: Particular palindromes 

    From The Sunday Times, 13th February 1983 [link]

    When either of a [particular] pair of numbers which differ by twenty-two is added to its own square, the result is a numerical palindrome between ten million and a hundred million.

    One way of finding the pair could be, of course, by extensive trial-and-error, working through the six thousand or so possibilities that lie in the given range, and electronic assistance would surely be appreciated in these circumstances.

    It should come as some relief, therefore, to puzzlers not so equipped to know that an answer can be found by performing less than twenty simple calculations (in which a calculator may nevertheless be usefully employed), none involving the square of a four-digit number, and that a further similar number of such calculations can show that no other answer is possible.

    What is the pair?

    This puzzle is included in the book The Sunday Times Book of Brainteasers (1994).

    [teaser1071]

     
    • Jim Randell's avatar

      Jim Randell 10:20 am on 5 March 2023 Permalink | Reply

      A brute force approach considers 6838 values, which is what the following Python program does.

      It runs in 61ms. (Internal runtime is 4.7ms).

      Run: [ @replit ]

      from enigma import (irange, inf, is_npalindrome, printf)
      
      # function to apply
      f = lambda x: x * (x + 1)
      
      # consider possible numbers
      vs = dict()
      for n in irange(0, inf):
        v = f(n)
        if v < 10000000: continue
        if v > 100000000: break
        # is the result a palindrome?
        if is_npalindrome(v):
          # have we recorded (n - 22)?
          v2 = vs.get(n - 22)
          if v2 is not None:
            # output solution
            printf("f({n}) = {v}; f({n2}) = {v2}", n2=n - 22)
          # record this value
          vs[n] = v
      

      Solution: The numbers are 5291, 5313.

      We have:

      5313 − 5291 = 22

      f(5291) = 27999972
      f(5313) = 28233282

      In fact these are the only two 8-digit palindromes that are the product of 2 consecutive integers.

      Like

      • Jim Randell's avatar

        Jim Randell 10:45 am on 5 March 2023 Permalink | Reply

        This puzzle was included in the book Microteasers (1986) by Victor Bryant.

        Here is the BBC BASIC program given in the text. It looks for palindromic 8-digit numbers that are the product of two consecutive integers, and prints them out. So it doesn’t look for a pair of numbers that differ by 22.

        >LIST
            5 REM Victor Bryant program for Teaser 1071
            6 REM from "Microteasers" (1986)
           10 REM We want N + N^2 to be an 8-digit palindrome
           15 start% = TIME
           20 N = 3000
           30 REPEAT
           40   N = N + 1
           50   M = N + N*N
           60   L = LEN(STR$(M))
           70   IF L <> 8 THEN 150
           80   REM We now work out the Dth digit from the right and the Dth digit from the left and see if they are the same
           90   D = 0
           91   REPEAT
           92     D = D + 1
          100     left$ = MID$(STR$(M), D, 1)
          110     right$ = MID$(STR$(M), 9 - D, 1)
          120   UNTIL D = 4 OR left$ <> right$
          130   REM if left$ = right$ when we get to this line then M = palindrome
          140   IF left$ = right$ THEN PRINT N, M
          150 UNTIL L > 8
          155 PRINT "Time = ";(TIME - start%) / 100;"s"
        >RUN
              5291  27999972
              5313  28233282
        Time = 322.32s
        >
        

        Like

      • Jim Randell's avatar

        Jim Randell 3:40 pm on 5 March 2023 Permalink | Reply

        A little bit of analysis can significantly reduce the number of cases tested:

        In order for n(n + 1) to be a palindrome it cannot be divisible by 10, so neither n nor (n + 1) can be divisible by 5 (as one of them will be even).

        And if (n + 22)(n + 23) is a palindrome, neither (n + 22) nor (n + 23) can be divisible by 5.

        So the residue of n mod 5 cannot be 0, 2, 3, 4. Hence it must be 1.

        So we only need to consider n values of the form (5k + 1).

        Also if n(n + 1) is an 8-digit palindrome, say ABCDDCBA then we have:

        n(n + 1) = 10000001.A + 1000010.B + 100100.C + 11000.D
        n(n + 1) = 11.(909091.A + 90910.B + 9100.C + 1000.D)

        So one of n, (n + 1) must be divisible by 11. (And also one of (n + 22), (n + 23) but that follows directly).

        So here is a program that only considers 248 candidate numbers, and has an internal runtime of 491µs.

        Run: [ @replit ]

        from enigma import (irange, inf, is_npalindrome, nsplit, printf)
        
        # function to apply
        f = lambda x: x * (x + 1)
        
        # consider possible numbers
        for n in irange(1, inf, step=5):
          if n % 11 not in {0, 10}: continue
          # apply the function
          v = f(n)
          if v < 10_000_000: continue
          v2 = f(n + 22)
          if v2 > 100_000_000: break
          # is the result a palindrome?
          if is_npalindrome(v) and is_npalindrome(v2):
            printf("f({n}) = {v}; f({n2}) = {v2}", n2=n + 2)
        

        In particular using this approach I was able to write a modified version of Victor’s BBC BASIC program that reduced the runtime from 5m22s (Victor’s original program) to 13.9s (my modified program).

        >LIST
           10 REM Modification of Victor Bryant program for Teaser 1071
           20 REM from "Microteasers" (1986)
           30 REM We want N + N^2 to be an 8-digit palindrome
           40 start% = TIME
           50 FOR N = 3161 TO 9999 STEP 5
           60   IF N MOD 11 <> 0 AND N MOD 11 <> 10 THEN 140
           70   P = N + N*N
           80   IF NOT FNpal(STR$(P)) THEN 140
           90   M = N + 22
          100   Q = M + M*M
          110   IF NOT FNpal(STR$(Q)) THEN 140
          120   PRINT N, P
          130   PRINT M, Q
          140 NEXT N
          150 PRINT "Time = ";(TIME - start%) / 100;"s"
          160 END
          170 REM check for 8 character palindrome
          180 DEF FNpal(M$)
          190   IF LEN(M$) <> 8 THEN =FALSE
          200   FOR D = 1 TO 4
          210     left$ = MID$(M$, D, 1)
          220     right$ = MID$(M$, 9 - D, 1)
          230     IF left$ <> right$ THEN =FALSE
          240   NEXT D
          250   =TRUE
        >RUN
              5291  27999972
              5313  28233282
        Time = 13.9s
        

        But the setter must have some other analysis in mind to reduce the number of calculations to less than 20.

        Like

    • GeoffR's avatar

      GeoffR 1:29 pm on 5 March 2023 Permalink | Reply

      
      # testing for (num + square(num)) between 10 million and 100 million approx.
      # LB = 3161 + 3161 ** 2 = 9,995,082
      # UB = 9999 + 9999 ** 2 = 99,990,000
      for n in range(3161, 10000):
        sum_prod = n + n ** 2
        # check if this number is a numerical palindrome
        if str(sum_prod) == str(sum_prod)[::-1]:
          # Second number is 22 more than first number
          n2 = n + 22
          sum_prod2 = n2 + n2 ** 2
          # check if this number is a numerical palindrome
          if str(sum_prod2) == str(sum_prod2)[::-1]:
            print(f"Pair of numbers are {n} and {n2}.")
            print(f"Associated Palindromes are {sum_prod} and {sum_prod2}.")
              
      # Pair of numbers are 5291 and 5313.
      # Associated Palindromes are 27999972 and 28233282.
      
      

      Like

    • GeoffR's avatar

      GeoffR 8:57 am on 6 March 2023 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % Pair of required numbers 
      var 3161..9999:N1;
      var 3161..9999:N2;
      
      % Palindrome digits for both palindromes
      var 1..9:A; var 0..9:B; var 0..9:C; var 0..9:D;
      var 1..9:G; var 0..9:H; var 0..9:I; var 0..9:J; 
       
      % Two eight digit palindromes
      var 10000000..99999999:ABCDDCBA = A * pow(10,7) + B * pow(10,6) + C * pow(10,5)
      + D * pow(10,4) + D * pow(10,3) + C * pow(10,2) + B * pow(10,1) + A;
      
      var 10000000..99999999: GHIJJIHG = G * pow(10,7) + H * pow(10,6) + I * pow(10,5)
      + J * pow(10,4) + J * pow(10,3) +  I * pow(10,2) + H * pow(10,1) + G;
      
      % Palindrome formation
      constraint N1 + N1 * N1 == ABCDDCBA;   % 1st 8-digit palindrome
      
      % Pair of numbers differ by twenty-two
      constraint N2 == N1 + 22;
      constraint N2 + N2 * N2 == GHIJJIHG;   % 2nd 8-digit palindrome
      
      solve satisfy;
      
      output ["Two required numbers are " ++ show(N1) ++ " and " ++ show(N2) 
      ++ "\n" ++ "Palindromes are " ++ show(ABCDDCBA) ++ " and " ++ show(GHIJJIHG)];
      
      % Two required numbers are 5291 and 5313
      % Palindromes are 27999972 and 28233282
      % ----------
      % ==========
      
      
      

      Like

    • John Crabtree's avatar

      John Crabtree 4:59 pm on 8 March 2023 Permalink | Reply

      f(N) = N(N+1) = “ABCDDCBA” = 0 (mod 11) as the sum of alternating digits is the same
      f(N+22) – f(N) = 44N + 506
      The first and last digits do not change. The second digit from the left, B, must either be the same or increase by 1.
      If it stays the same, 44N + 506 = 0 (mod 100) with no solution.
      If it increases by 1, 44N + 506 = 10 (mod 100) which leads to N = 16 mod 25

      41*42 = 66*67 = 22 (mod 100)
      sqrt(22) = 4.690 and sqrt(23) = 4.795
      4741 = 0 (mod 11), but f(4741+22) must start with 22 and is invalid
      4766 = 3 (mod 11)

      16*17 = 91*92 = 72 (mod 100)
      sqrt(27) = 5.196 and sqrt(28) = 5.291
      5191 = 10 (mod 11), but is too small
      5216 = 2 (mod 11)
      5291 = 0 mod 11, and f(5191+22) must start with 28

      And so the numbers must be 5291 and 5313.
      At this point the calculator is very useful to find that
      f(5291) = 27,999,922 and f(5313) = 28,233,282

      There are not many calculations in this solution. I do not understand the setter’s statement about needing as many calculations again to show that the solution is unique. That is included above.

      Like

      • John Crabtree's avatar

        John Crabtree 5:50 am on 10 March 2023 Permalink | Reply

        Simplifying, N = -34 + 275k = 10 (mod 11); or N = 66 + 275k = 0 (mod 11)
        With AB = 22 or 27, there are only two possible values of N:
        4741 = 4675 (17 * 275) + 66, but f(4741 + 22) is invalid
        5291 = 5225 (19 * 275) + 66, and f(5291 + 22) = f(5313) is valid

        Like

  • Unknown's avatar

    Jim Randell 4:17 pm on 3 March 2023 Permalink | Reply
    Tags:   

    Teaser 3154: Gill’s primes 

    From The Sunday Times, 5th March 2023 [link] [link]

    Jack told Gill: “I have found three equally-spaced prime numbers 29, 41, and 53. The difference between the first and second is the same as the difference between the second and third, and there are no repeated digits in the six digits of my primes”. Gill told Jack she had also found three equally-spaced primes, each having three digits and with no repeated digits in the nine digits of her primes. She said: “If I told you that the three-digit sum of each of my primes is an odd number then you should be able to find them”.

    In ascending order what are Gill’s three primes?

    [teaser3154]

     
    • Jim Randell's avatar

      Jim Randell 4:30 pm on 3 March 2023 Permalink | Reply

      I am assuming that “the three-digit sum of each of my primes is an odd number”, means that for each prime the sum of the three digits gives an odd number (as this does indeed eliminate a second candidate solution).

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

      The following run file executes in 121ms. (Internal runtime of the generated program is 8.3ms).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      # suppose the primes are: ABC, DEF, GHI
      
      SubstitutedExpression
      
      # the numbers are prime
      "is_prime(ABC)"
      "is_prime(DEF)"
      "is_prime(GHI)"
      
      # the primes are ordered
      "A < D < G"
      
      # the primes form an arithmetic sequence
      "DEF - ABC == GHI - DEF"
      
      # each prime has an odd digit sum
      "(A + B + C) % 2 == 1"
      "(D + E + F) % 2 == 1"
      "(G + H + I) % 2 == 1"
      
      --template="ABC DEF GHI"
      --solution=""
      

      Solution: Gill’s primes are: 157, 283, 409.

      The common difference is 126, and each prime has a digit sum of 13.

      Without the stipulation that the digit sum of each prime is odd there would be a second solution, with the primes: 109, 283, 457.

      In this case the common difference is 174, and the digit sums are: 10, 13, 16.

      Like

    • GeoffR's avatar

      GeoffR 4:51 pm on 3 March 2023 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:A; var 0..9:B; var 1..9:C; 
      var 1..9:D; var 0..9:E; var 1..9:F; 
      var 1..9:G; var 0..9:H; var 1..9:I;
      
      constraint all_different([A,B,C,D,E,F,G,H,I]);
      
      predicate is_prime(var int: x) = x > 1 
      /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x))))) 
      ((i < x) -> (x mod i > 0));
      
      var 100..999:ABC = 100*A + 10*B + C;
      var 100..999:DEF = 100*D + 10*E + F;
      var 100..999:GHI = 100*G + 10*H + I;
      
      constraint sum([is_prime(ABC), is_prime(DEF), is_prime(GHI)]) == 3;
      constraint ABC < DEF /\ DEF < GHI;
      constraint DEF - ABC == GHI - DEF;
      
      constraint sum([(A+B+C) mod 2 == 1, (D+E+F) mod 2 == 1,
      (G+H+I) mod 2 == 1]) == 3;
      
      solve satisfy;
      
      output ["Gill's three primes are " ++ show(ABC) ++ ", " 
      ++ show(DEF) ++ ", " ++ show(GHI)];
      
      

      Like

    • Hugo's avatar

      Hugo 11:33 am on 12 March 2023 Permalink | Reply

      Sum 849, common difference 126, again with no repeated digit between them.
      The previous member of the arithmetic progression, 31, is also prime, but it has only two digits and they’re both repeats of ones in the solution.

      “the three-digit sum of each of my primes” is indeed an odd way of expressing it.

      Like

    • Frits's avatar

      Frits 12:25 pm on 27 March 2023 Permalink | Reply

      Use primes ooo, eeo and eeo (o = odd and e = even).

         
      from enigma import SubstitutedExpression
      
      # invalid digit / symbol assignments
      d2i = dict()
      for d in range(0, 10):
        vs = set()
        if d == 0: vs.update('ADG')
        # A, B, C, F and I must be odd
        if d % 2 == 0: vs.update('ABCFI')
        else: vs.update('DEGH')
        
        if d == 8: vs.update('D')
        if d == 2: vs.update('G')
          
        d2i[d] = vs
      
      # the alphametic puzzle
      p = SubstitutedExpression(
        [
          # prime ooo
          "is_prime(ABC)",
          # prime eeo
          "is_prime(DEF)",
          "D < G",
          # missing digit must be 0 or 6 (as sum of all 9 digits is a multiple of 3)
          "len({D, E, G, H}.difference([2, 4, 8])) == 1",
          # prime eeo
          "is_prime(GHI)",
          
          # the primes form an arithmetic sequence
          "(srt := sorted([ABC, DEF, GHI]))[2] == 2 * srt[1] - srt[0]",
        ],
        answer="srt",
        d2i=d2i,
        distinct=("ABCFI", "DEGH"),
        #reorder=0,
        verbose=0,    # use 256 to see the generated code
      )
      
      # print answers
      for (_, ans) in p.solve():
        print(f"{ans}")
      

      Like

  • Unknown's avatar

    Jim Randell 11:28 am on 2 March 2023 Permalink | Reply
    Tags: by: J M Leonard   

    Brain-Teaser 259: [Musical tastes] 

    From The Sunday Times, 17th April 1966 [link]

    A survey of the musical tastes of 100 boys showed that the most popular group was one known as the Jonahs, three girls by the names of Jane, Jean and June.

    58 were fans of Jane, 45 fans of Jean, and 42 fans of June. Jane and Jean had 27 fans in common; Jane and June, 28; Jean and June 19; and 18 were fans of all three.

    How many of the boys were not fans of the group?

    This puzzle was originally published with no title.

    [teaser259]

     
    • Jim Randell's avatar

      Jim Randell 11:30 am on 2 March 2023 Permalink | Reply

      We can label the 8 areas of the corresponding Venn diagram according to who likes who:

      (Jane) = a
      (Jean) = b
      (June) = c
      (Jane + Jean) = d
      (Jean + June) = e
      (Jane + June) = f
      (Jane + Jean + June) = g
      () = x

      and we have:

      a + b + c + d + e + f + g + x = 100
      a + d + g + f = 58
      b + e + d + g = 45
      c + e + f + g = 42
      d + g = 27
      g + f = 28
      e + g = 19
      g = 18

      These equations are easily solved manually to give:

      g = 18
      e = 1
      f = 10
      d = 9
      a = 21
      b = 17
      c = 13
      x = 11

      Solution: 11 of the boys were not fans of any member of the group.


      Here is a program using the [[ Matrix() ]] class from the enigma.py library.

      Run: [ @replit ]

      from enigma import (Matrix, as_int, printf)
      
      # construct the equations
      eq = Matrix.equation("abcdefgx")
      eqs = [
        eq("abcdefgx", 100),
        eq("adgf", 58), eq("bedg", 45), eq("cefg", 42),
        eq("dg", 27), eq("gf", 28), eq("eg", 19),
        eq("g", 18),
      ]
      
      # solve the equations
      (a, b, c, d, e, f, g, x) = Matrix.linear(eqs, valid=(lambda n: as_int(n, "0+")))
      
      # output the solution
      printf("x={x} [a={a} b={b} c={c} d={d} e={e} f={f} g={g}]")
      

      Like

  • Unknown's avatar

    Jim Randell 9:18 am on 28 February 2023 Permalink | Reply
    Tags:   

    Teaser 2715: Colour coded 

    From The Sunday Times, 5th October 2014 [link] [link]

    Five lads cycle together daily. Each has a different number of helmets, less than a dozen, and none of them has two of the same colour. Each wears in daily rotation all the cycle helmets he possesses. On 1st September, Alan wore mauve, Bill and Charles wore red, Dave orange and Eric green. On 11th September, two were red, one green, one mauve and one white. On 19th September, Dave’s was orange, Eric’s green and the others red. Eric wore orange on the 22nd and white on the 23rd. On 1st October all five wore the same as on 1st September.

    In alphabetical order of the riders, what were the helmet colours on the 11th September?

    [teaser2715]

     
    • Jim Randell's avatar

      Jim Randell 9:18 am on 28 February 2023 Permalink | Reply

      I am assuming that each cyclist cycles(!) through their helmets in strict rotation. So each time through they wear the same colours in the same order.

      None of them have duplicate colours, so if we see one of them wearing the same colour on different days, they must have completed a whole number of cycles between those days. And they are all wearing the same colours on 1st September and 1st October, so the length of each of their cycles must be a divisor of 30, less than 12 (i.e. 1, 2, 3, 5, 6, 10).

      For any given cyclist, if we are given a set of days and colours then we can look at days when the same colour is worn. The gap between the days must be a multiple (possibly 1) of the cycle length. And so by considering all possible gaps we can can determine possible cycle lengths. Furthermore, different colours must be worn on different days in the cycle. So

      This Python program calculates possible cycle lengths from the colours given on the specified dates.

      It runs in 55ms. (Internal runtime is 2.2ms).

      Run: [ @replit ]

      from enigma import (
        subsets, group, unpack, union, tuples, mgcd, divisors,
        seq_all_different, delete, update, rev, map2str, printf
      )
      
      # find cycle lengths for values give in ms
      def solve(ms, ns=dict()):
        # are we done?
        if not ms:
          yield ns
        else:
          # choose a key to process (the one with the most entries)
          x = max(ms.keys(), key=(lambda k: len(ms[k].keys())))
          # group days by colour
          g = group(ms[x].items(), by=unpack(lambda k, v: v), f=unpack(lambda k, v: k))
          # collect multiples of cycle length
          s = union((abs(b - a) for (a, b) in tuples(vs, 2)) for vs in g.values())
          # consider possible cycle lengths (must be < 12)
          for n in divisors(mgcd(*s)):
            if n > 11: break
            # is this one already used?
            if n in ns: continue
            # check different colours give different cycle days
            if not seq_all_different(vs[0] % n for vs in g.values()): continue
            # solve for the remaining items
            yield from solve(delete(ms, [x]), update(ns, [(n, x)]))
      
      # consider possible orderings for 11th
      for (a, b, c, d, e) in subsets('RRGMW', size=len, select='mP'):
        # known positions (day 1 = 1st September)
        ms = dict(
          A={ 1: 'M', 11: a, 19: 'R', 31: 'M' },
          B={ 1: 'R', 11: b, 19: 'R', 31: 'R' },
          C={ 1: 'R', 11: c, 19: 'R', 31: 'R' },
          D={ 1: 'O', 11: d, 19: 'O', 31: 'O' },
          E={ 1: 'G', 11: e, 19: 'G', 22: 'O', 23: 'W', 31: 'G' },
        )
        # find possible cycle lengths
        for ns in solve(ms):
          # output solution
          printf("day 11: (A B C D E) = ({a} {b} {c} {d} {e}) {ns}", ns=map2str(rev(ns), sep=" ", enc="[]"))
      

      Solution: On 11th September, the colours were: Alan = mauve; Bill = red; Charles = red; Dave = green; Eric = white.

      Alan has 5 or 10 helmets. Bill has 1 or 2. Charles has 2 or 1. Dave has 3. Eric has 6.

      We can’t work out all the colours, but here is what we do know:

      A: (M ? ? ? ?) or (M ? ? ? ? ? ? ? ? ?)
      B: (R) or (R ?)
      C: (R ?) or (R)
      D: (O ? ?)
      E: (G ? ? O W ?)

      However these cycle lengths are chosen, they all give the same sequence of values for the 11th September.

      Like

  • Unknown's avatar

    Jim Randell 9:44 am on 26 February 2023 Permalink | Reply
    Tags:   

    Brain-Teaser 845: Hymn boards again 

    From The Sunday Times, 25th September 1977 [link] [link]

    I bade the Admiral good morning as I came out of church on Sunday morning, adding: “Did you notice anything odd about the hymns today?”.

    “Odd?”, he snorted; “they always sound odd to me, and they always will so long as Mrs. Haslet bellows her tuneless version at the back of my neck. A good enough woman in so many respects, but she doesn’t know a B-flat from a bull’s foot”.

    “No”, I said hastily, “I was referring to the mathematical rather than the musical aspect. There were, you will recall, three hymns all of three digits. Each digit appeared once only, and there were no zeros. The sums of the digits in all three hymns were equal and, what is more, the sum of the three hymn-numbers was a perfect square containing THREE digits. Very odd”.

    “Yes, I suppose so”, replied the Admiral, “… I do wish Mrs. Haslet would sit somewhere else”.

    What were the hymn numbers in ascending order (appropriately enough)?

    This puzzle is also included in the book The Sunday Times Book of Brain-Teasers: Book 2 (1981). Where it appears in the following form as Puzzle 50b:

    The Sunday before last the board also provided me with some mathematical interest. There were three hymns and again each digit from 1 to 9 inclusive was used. The sums of the digits in all three hymns were equal and, what is more, the sum of all three hymn numbers was a perfect square containing three digits.

    What were the hymn numbers on that Sunday?

    [teaser845]

     
    • Jim Randell's avatar

      Jim Randell 9:47 am on 26 February 2023 Permalink | Reply

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

      The following run file executes in 81ms. (Internal runtime of the generated program is 17ms).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --digits="1-9"
      
      # digit sums are all the same
      "A + B + C == D + E + F"
      "D + E + F == G + H + I"
      
      # sum of the numbers is a 3-digit perfect square
      "9 < is_square(ABC + DEF + GHI) < 32"
      
      # remove duplicate solutions
      "A < D < G"
      
      --answer="(ABC, DEF, GHI)"
      

      Solution: The hymn numbers were: 195, 267, 438.

      Like

    • GeoffR's avatar

      GeoffR 12:01 pm on 26 February 2023 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:A; var 1..9:B; var 1..9:C; % Hymn ABC digits
      var 1..9:D; var 1..9:E; var 1..9:F; % Hymn DEF digits
      var 1..9:G; var 1..9:H; var 1..9:I; % Hymn GHI digits
      
      constraint all_different([A, B, C, D, E, F, G, H, I])
      /\ A < D /\ D < G;
      
      set of int: sq3 = { pow(x, 2) | x in 10..31 };
      
      constraint A + B + C == D + E + F /\ A + B + C == G + H + I
      /\ (100*A + 10*B + C)  +  (100*D + 10*E + F) + (100*G + 10*H + I) in sq3;
      
      solve satisfy;
      
      output ["Hymn Numbers were \(A)\(B)\(C)" ++  ", \(D)\(E)\(F)"
      ++  " and \(G)\(H)\(I)." ];
      
      % Hymn Numbers were 195, 267 and 438.
      % ----------
      % ==========
      
      
      

      Like

    • GeoffR's avatar

      GeoffR 9:09 am on 2 March 2023 Permalink | Reply

      
      from itertools import permutations
      from enigma import is_square
      
      for p1 in permutations(range(1, 10)):
          A, B, C, D, E, F, G, H, I = p1
          if A < D < G:  # order three hymn numbers
              if not(A + B + C == D + E + F):continue
              if not(A + B + C == G + H + I):continue
              total = 100 *(A + D + G) + 10 * (B + E + H) + (C + F + I)
              if is_square(total) and 100 < total < 1000:
                  ABC, DEF = 100*A + 10*B + C, 100*D + 10*E + F
                  GHI = 100*G + 10*H + I
                  print(f"Hymn Numbers were {ABC}, {DEF}, {GHI}")
      
      

      Like

    • Jim Randell's avatar

      Jim Randell 9:56 am on 2 March 2023 Permalink | Reply

      I thought it would be interesting to ask ChatGPT to write a Python program to solve this puzzle:

      Write a Python program to find a set of three 3-digit numbers, using each of the digits 1-9 exactly once between them. The sum of the digits in each of the three numbers is the same. The sum of the three numbers is a 3-digit perfect square. There is only one set of numbers that satisfies these conditions.

      And it produced this (without further prompting):

      import itertools
      
      # Generate all permutations of the digits 1-9
      perms = itertools.permutations(range(1, 10))
      
      # Loop through each permutation and check if it satisfies the conditions
      for perm in perms:
        # Split the permutation into three 3-digit numbers
        a, b, c = perm[:3], perm[3:6], perm[6:]
      
        # Check that each number contains no repeated digits
        if len(set(a)) == len(a) == len(set(b)) == len(b) == len(set(c)) == len(c):
          # Check that the sum of digits in each number is the same
          if sum(a) == sum(b) == sum(c):
            # Check that the sum of the three numbers is a 3-digit perfect square
            total = int("".join(map(str, a))) + int("".join(map(str, b))) + int("".join(map(str, c)))
            if len(str(total)) == 3 and int(total ** 0.5) ** 2 == total:
              # Print the solution and break out of the loop
              print(a, b, c)
              break
      

      It is hardly an elegant or efficient approach (and the check that each number contains no repeated digits is not necessary), but there is no arguing with the fact that it does correctly find the solution to the puzzle.

      I then tried to get it to improve the program. Firstly by removing the unnecessary check (which it did), and then by performing an exhaustive search in case there are further solutions while avoiding duplicate solutions. It took a bit of discussion to get it to implement this second improvement correctly, but here is the final program:

      import itertools
      
      # Join the digits in the given list of numbers into a single integer
      def join_and_convert(nums):
        return int(''.join(map(str, nums)))
      
      # Generate all permutations of the digits 1-9
      digits = range(1, 10)
      permutations = itertools.permutations(digits)
      
      # Find sets of three numbers with the same digit sum and sum to a perfect square
      solutions = set()
      for p in permutations:
        a, b, c = p[:3], p[3:6], p[6:]
        if sum(a) == sum(b) == sum(c):
          total = join_and_convert(a) + join_and_convert(b) + join_and_convert(c)
          if len(str(total)) == 3 and int(total ** 0.5) ** 2 == total:
            solution = tuple(sorted([a, b, c]))
            if solution not in solutions:
              solutions.add(solution)
              print(solution)
      

      Like

    • GeoffR's avatar

      GeoffR 12:09 pm on 2 March 2023 Permalink | Reply

      @Jim: Very Interesting experiment, both for the original program and the second solution. Would it be possible to ask ChatGPT to write a program in other languages?

      Like

      • Jim Randell's avatar

        Jim Randell 3:10 pm on 2 March 2023 Permalink | Reply

        @GeoffR: I don’t think ChatGPT has been specifically trained in Python (or indeed in programming). But as Python is quite a popular language amount of it was probably present in the data it was trained on.

        What ChatGPT is doing is attempting to provide a likely continuation of the conversation I started with my question. It has been trained on an extremely large data set, so it is able to give a plausible looking answer to a wide variety of questions.

        However it is very much a jack of all trades, master of none. If you have asked a vague question on a subject you are not too familiar the plausible sounding answer feels like it might be right. But if you ask a specific question on something you know a lot about you soon discover that it will confidently state an answer that is fundamentally flawed.

        When it confidently produces a program and claims that it solves the problem you gave it, what it is really saying is: “problems that look similar to the problem you set can be solved by programs that look similar to the program I have given”.

        Jim: Which weighs more, a pound of feathers or 2 pounds of bricks?

        ChatGPT: Both the pound of feathers and the 2 pounds of bricks weigh the same, which is 1 pound.

        The confusion may arise because when we hear “2 pounds of bricks”, our mind may immediately think of the number “2” and assume that it must weigh more than just “1”. However, the key here is to pay attention to the unit of measurement, which is pounds.

        In summary, a pound of feathers and 2 pounds of bricks weigh the same amount, which is 1 pound.

        And you can ask it to justify this incorrect position, and it will produce more paragraphs of plausible sounding rubbish. Sometimes the plausible sounding answer will be a correct response to a question, but it is able to bluff its way though a remarkably wide variety of subjects.

        I have tried asking it to solve a few puzzles before, and this is the first it has actually succeeded on. But you do need to understand the puzzle yourself (and if you have asked it to write a program, the programming language too), to be able to gauge how useful the plausible sounding response it produces is.

        Like

    • GeoffR's avatar

      GeoffR 5:06 pm on 2 March 2023 Permalink | Reply

      @Jim: Thanks for the detailed appraisal.

      I found a link stating that ChatGPT is written in Python and knows 12 programming languages:

      https://seo.ai/blog/how-many-languages-does-chatgpt-support#:~:text=ChatGPT%20is%20mainly%20focused%20on,JavaScript

      Like

  • Unknown's avatar

    Jim Randell 4:37 pm on 24 February 2023 Permalink | Reply
    Tags:   

    Teaser 3153: Pole position 

    From The Sunday Times, 26th February 2023 [link] [link]

    Jeb’s 25×25km square ranch had his house’s flagpole at the ranch’s pole of inaccessibility (the point whence the shortest distance to a boundary fence was maximised).

    At 50, Jeb gave each of his four sons a triangular tract of his land, with corners whole numbers of km along boundary fences from each corner post (as illustrated, not to scale). Each tract’s area (in square km) equalled that son’s age last birthday (all over 19, but under 30). All the tracts’ perimeters differed, and each son set his hacienda’s flagpole at his own tract’s pole of inaccessibility.

    Curiously, for Jeb’s new octagonal ranch the pole of inaccessibility and the shortest distance from this to a boundary fence were unchanged.

    Give the eldest son’s shortest distance from his flagpole to a boundary fence.

    This puzzle marks the 62nd birthday of the Sunday Times Brain Teaser puzzle. The first numbered puzzle, Brain-Teaser 1: Tall story, was published on 26th February 1961.

    [teaser3153]

     
    • Jim Randell's avatar

      Jim Randell 5:09 pm on 24 February 2023 Permalink | Reply

      We can calculate which of the possible triangles do not change the pole of inaccessibility, and it turns out there are exactly 4 of them (and they do have different perimeters). We can then calculate the inradius of the one with the largest area to find the required answer.

      This Python program runs in 51ms. (Internal runtimes is 259µs).

      Run: [ @replit ]

      from enigma import (irange, subsets, div, hypot, fdiv, line_distance, Accumulator, printf)
      
      # distance to boundary from pole
      R = 12.5  # = 0.5 * 25 km
      
      # record inradius for maximum age
      m = Accumulator(fn=max)
      
      # consider (a, b) plots for the sons
      for (a, b) in subsets(irange(1, int(R)), size=2, select="R"):
        # calculate area
        A = div(a * b, 2)
        # check for viable area, and age
        if A is None or not (19 < A < 30): continue
        # check boundary does not change the pole of accessibility
        if line_distance((0, a), (b, 0), (R, R)) < R: continue
        # calculate the perimeter
        p = a + b + hypot(a, b)
        # calculate inradius; area = inradius * semiperimeter
        r = fdiv(2 * A, p)
        printf("({a}, {b}) -> A={A}; p={p:.3f}; r={r:.3f}")
        m.accumulate_data(A, r)
      
      # output solution (inradius for maximum age)
      printf("answer = {m.data} km")
      assert m.count == 4  # check that 4 plots were found
      

      Solution: The shortest distance from the eldest son’s flagpole to a boundary is 2 km.


      Given a plot of land a “pole of inaccessibility” is the centre of a maximal radius circle that can be placed inside that plot without exceeding the boundaries.

      So for the square plot of land the flagpole is erected at the centre of the square. (For a non-square rectangle there would a line of possible positions where the flagpole could be erected). And for a triangle the flagpole is erected at the incentre (i.e. the centre of the incircle) of the triangle. (See [@wikipedia]).

      The plots of land, and positions of the flagpoles, are illustrated in the diagram below:

      Jeb’s flagpole is at the centre of the square, and the large red circle shows the shortest distance to a boundary. When the corner plots are made they cannot cross the large red circle, or they would reduce the shortest distance from Jeb’s flagpole to a boundary. But they could touch the circle.

      There are 4 different triangular plots that can be made, and they are also shown on the diagram, along with their incentres, which correspond to the positions of the sons’ flagpoles.

      The boundary of the plot on the bottom left (with an area of 20) comes closest to Jeb’s flagpole (it is 12.534 km away from it). The plot on the bottom right (with an area of 24) is the largest. The other two plots have areas of 20 and 21.

      Like

    • Hugo's avatar

      Hugo 9:41 am on 5 March 2023 Permalink | Reply

      Sides of the triangular plots (with area and distance of third side from the centre of the square):
      4, 10 (20, 12.534) nearly touched the big circle
      5, 8 (20, 12.985)
      6, 7 (21, 13.07)
      6, 8 (24, 12.7) third side 10
      There would be a couple more with two integer sides but half-integer areas.

      Like

  • Unknown's avatar

    Jim Randell 8:18 am on 21 February 2023 Permalink | Reply
    Tags:   

    Teaser 2716: Millennial squares 

    From The Sunday Times, 12th October 2014 [link] [link]

    I asked my class to take some pieces of card and to write a digit on each side of each card so that any year of this millennium that is a perfect square could be spelt out using four of the cards. One clever pupil achieved this with the smallest number of cards possible. He also pointed out that with his cards he could go way beyond the end of this millennium — in fact he had designed them so that, when trying to make this list of consecutive square years yet to come, he was able to go as far as possible with that number of cards.

    What is the last square he could make?

    [teaser2716]

     
    • Jim Randell's avatar

      Jim Randell 8:19 am on 21 February 2023 Permalink | Reply

      First we note that the digit 9 can use the same symbol as the digit 6, so we only need to consider the symbols 0-8. (Although it turns out that we get the same answer even if the digits 6 and 9 use different symbols).

      We can quickly find a theoretical minimum collection of symbols required to express the squares between 2001 – 3000 by considering the multiset union of each of those squares (considered as a multiset of corresponding symbols). And with two symbols per card we can determine the theoretical minimum number of cards required to accommodate these symbols. (Although this does not tell us that an appropriate set of cards can be constructed).

      We can then start adding in additional squares until we can no longer fit all the required symbols on the required number of cards, and this gives us a theoretical maximum constructible square to answer the puzzle.

      We can then check that this solution is achievable by constructing a collection of cards of the appropriate size that allows all the required squares to be made.

      This Python program runs in 56ms. (Internal runtime is 809µs).

      Run: [ @replit ]

      from enigma import (irange, inf, sq, nsplit, join, multiset, divc, delete, cache, printf)
      
      # symbols used to represent digits (6 and 9 are the same symbol)
      sym = dict(zip(irange(0, 9), "0123456786"))
      
      # words to be spelled out
      word = cache(lambda n: join(sym[d] for d in nsplit(n)))
      
      # find the minimum number of cards required (n symbols per card)
      min_cards = lambda m, n=2: divc(m.size(), n)
      
      # collect the symbols required to make the initial set of numbers
      ns = list(sq(i) for i in irange(45, 54))
      m = multiset()
      for n in ns:
        m.union_update(word(n))
      k = min_cards(m)
      printf("{k} cards = [{a} .. {b}] ({s} symbols)", a=ns[0], b=ns[-1], s=m.size())
      
      # add extra numbers until another card is required
      for i in irange(55, inf):
        n = sq(i)
        w = word(n)
        m_ = m.union(w)
        k_ = min_cards(m_)
        printf("{k_} cards = [{a} .. {b}] ({s} symbols)", a=ns[0], b=n, s=m_.size())
        if k_ > k: break
        ns.append(n)
        m = m_
      
      # now try to construct a set of <k> cards that covers the numbers <ns>
      
      # can we make word <w> with cards <cs>
      def make(w, cs):
        if not w:
          return True
        x = w[0]
        for (i, c) in enumerate(cs):
          if x in c and make(w[1:], delete(cs, [i])):
            return True
        return False
      
      # make a set of <k> cards, the can make words <ws>, symbol counts in <m>
      def cards(k, ws, m, cs=[]):
        # are we done?
        if k == 0:
          if all(make(w, cs) for w in ws):
            yield tuple(sorted(cs))
        elif k > 0 and m:
          # make the next card
          x = m.min()
          for y in m.keys():
            if x < y:
              c = x + y
              if (not cs) or (not c < cs[-1]):
                yield from cards(k - 1, ws, m.difference([x, y]), cs + [c])
      
      # try to make a <k>-set of cards that covers numbers <ns>
      if m.size() % 2 == 1: m.add('?')
      for cs in cards(k, list(word(n) for n in ns), m):
        printf("cards = {cs}", cs=join(cs, sep=" ", enc="()"))
        break
      

      Solution: The last square that he could make was 3721.


      To make the squares 2025 – 2916 requires a collection of 13 symbols, so we need 7 cards to accommodate these.

      And if we also include the squares up to 3721 then we need a collection of 14 symbols, which still requires 7 cards.

      But to also include the next square (3844) would require 15 symbols (as we need to have two 4’s), and this cannot be accommodated with 7 cards.

      There are many sets of 7 cards that allow the squares 2025 – 3721 to be made, for example:

      (02 07 13 18 26 39 45)

      (And this set works if 6 and 9 are different digits, or if they are the same digit).

      Like

  • Unknown's avatar

    Jim Randell 3:36 pm on 19 February 2023 Permalink | Reply
    Tags:   

    Brain-Teaser 402: Book pages 

    From The Sunday Times, 19th January 1969 [link]

    A famous book by Brian Teezer has eight chapters, each starting on a right-hand page. All the chapters except one have a half-page of footnotes, which are printed separately after each chapter.

    Each chapter has one more page than the preceding chapter, the last chapter having fewer than 30 pages.

    The current edition of the book contains 200 pages, but the printer has pointed out that when a reprint is issued he can save four pages by assembling the footnotes at the end of chapter 8.

    How many completely blank pages are there in the current edition, and how many will there be in the reprint?

    This puzzle is included in the book Sunday Times Brain Teasers (1974), and is also reproduced on the back cover of the paperback copy of the book I have.

    [teaser402]

     
    • Jim Randell's avatar

      Jim Randell 3:43 pm on 19 February 2023 Permalink | Reply

      This Python program considers the possible numbers of pages for each chapter, and which chapter has no footnotes, until it finds an arrangement that requires 200 pages for the book. It then checks if collecting the footnotes together will save 4 pages.

      It runs in 59ms. (Internal runtime is 817µs).

      Run: [ @replit ]

      from enigma import (irange, tuples, printf)
      
      # allocate pages for the current edition
      def allocate(ps, fs):
        # count blank pages
        b = 0
        # start on page 1
        t = 1
        for (i, p) in enumerate(ps, start=1):
          # allocate the pages for the chapter
          t += p
          # and the footnotes (if necessary)
          t += fs.get(i, 0)
          # insert a blank page (if necessary)
          if t % 2 == 0:
            b += 1
            t += 1
        # return (<total number of pages>, <blank pages inserted>)
        return (t - 1, b)
      
      # consider the number of pages in each chapter
      for ps in tuples(irange(1, 29), 8):
        # consider the chapter with no footnotes
        for nf in irange(1, 8):
          fs = dict((i, 1) for i in irange(1, 8) if i != nf)
          (t, b) = allocate(ps, fs)
          # current edition has 200 pages
          if t == 200:
            # move the 3.5 pages of footnotes to the end of chapter 8
            (t_, b_) = allocate(ps, { 8: 4 })
            # this should save 4 pages
            if t_ + 4 == t:
              # output solution
              printf("chapters = {ps}; nf={nf}")
              printf("  -> cur: pages = {t} total, {b} blank")
              printf("  -> new: pages = {t_} total, {b_} blank")
              printf()
      

      Solution: There are 5 completely blank pages in the current edition. In the reprint there will be 4.

      Chapter 1 has 20 pages, and each subsequent chapter has 1 more page, up to chapter 8 with 27 pages.

      The chapter with no footnotes can be any one of chapters 2, 4, 6, 8, to give a current edition with 200 pages.

      Collecting the 3.5 pages of footnotes together at the end of chapter 8 brings the total number of pages down to 196.

      Like

  • Unknown's avatar

    Jim Randell 4:00 pm on 17 February 2023 Permalink | Reply
    Tags:   

    Teaser 3152: Stamps of approval 

    From The Sunday Times, 19th February 2023 [link] [link]

    I really like the postcards that a friend of mine has sent me each of the last three years from her annual holiday in Farflung. Each card had six stamps on it, involving the same four denominations, and at least one of each denomination was present on each card. These four denominations were all different and coloured differently, and of course represented whole numbers of pecahans. I can’t read what the denominations are, but my friend had remarked the postage totals for the three years were 23, 32 and 36 pecahans.

    What were the four denominations, in decreasing order?

    [teaser3152]

     
    • Jim Randell's avatar

      Jim Randell 4:16 pm on 17 February 2023 Permalink | Reply

      The following Python program considers possible sets of 4 denominations, and then looks to see if each of the required amounts can be made using these denominations, using 6 stamps, with at least one of each denomination.

      It runs in 89ms. (Internal runtime is 31ms).

      Run: [ @replit ]

      from enigma import (irange, tri, decompose, express, printf)
      
      # can we make value <v> from denominations <ds> using exactly <k> stamps?
      def make(v, ds, k):
        return list(qs for qs in express(v, ds, min_q=1) if sum(qs) == k)
      
      # amounts to make (ordered)
      vs = [23, 32, 36]
      
      # consider possible sets of stamps
      for t in irange(tri(4), vs[0] - 2):
        for ds in decompose(t, 4, increasing=1, sep=1, min_v=1):
          # can we make each amount using 6 stamps?
          xs = list(make(v, ds, 6) for v in vs)
          if all(xs):
            # output solution
            printf("stamps = {ds} [t = {t}]")
            for (v, qs) in zip(vs, xs):
              printf("-> {v} = {qs}")
            printf()
      

      Solution: The four denominations are: 9, 6, 5, 1 pecahans.

      And we can make the amounts using 6 stamps as follows:

      23 = 9 + 6 + 5 + 1 + 1 + 1
      32 = 9 + 6 + 6 + 5 + 5 + 1
      36 = 9 + 9 + 6 + 6 + 1 + 1

      And these are the only ways to make the required amounts.

      Like

      • Jim Randell's avatar

        Jim Randell 12:31 pm on 18 February 2023 Permalink | Reply

        Here is a faster version of my program.

        It starts by making a list of the decompositions of 6 stamps from 4 different denominations (where each denomination is represented). And then looks for sets of denominations that allow each of the required values to be made using (at least) one of the decompositions from the list.

        It runs in 61ms. (Internal runtime is 1.8ms).

        Run: [ @replit ]

        from enigma import (irange, tri, decompose, group, dot, printf)
        
        # possible arrangements for 6 stamps of 4 different denominations
        qss = list(decompose(6, 4, increasing=0, sep=0, min_v=1))
        
        # amounts to make (ordered)
        vs = [23, 32, 36]
        
        # consider total value of one stamp of each denomination
        for t in irange(tri(4), vs[0] - 2):
          # split the total into 4 different denominations
          for ds in decompose(t, 4, increasing=1, sep=1, min_v=1):
            # collect amounts that can be made from the arrangements
            g = group(qss, by=(lambda qs: dot(qs, ds)))
            # can we make each amount using 6 stamps?
            if all(g.get(v) for v in vs):
              # output solution
              printf("stamps = {ds} [t = {t}]")
              for v in vs:
                printf("-> {v} = {qs}", qs=g.get(v))
              printf()
        

        Like

    • GeoffR's avatar

      GeoffR 6:20 pm on 17 February 2023 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      % Four different denominations of the stamps
      var 1..15:d1; var 1..15:d2; var 1..15:d3; var 1..15:d4;
      constraint all_different([d1, d2, d3, d4]);
      
      % Stamp numbers in each of three years
      var 1..3:a; var 1..3:b; var 1..3:c; var 1..3:d; % year 1 no. stamps
      var 1..3:e; var 1..3:f; var 1..3:g; var 1..3:h; % year 2 no. stamps
      var 1..3:i; var 1..3:j; var 1..3:k; var 1..3:m; % year 3 no. stamps
      
      % Stamp total values for each of three years are 23, 32 and 36 pecahans.
      constraint a * d1 + b * d2 + c * d3 + d * d4 == 23 /\ a + b + c + d == 6;
      constraint e * d1 + f * d2 + g * d3 + h * d4 == 32 /\ e + f + g + h == 6;
      constraint i * d1 + j * d2 + k * d3 + m * d4 == 36 /\ i + j + k + m == 6;
      
      % Order stamp denominations
      constraint decreasing ([d1, d2, d3, d4]);
      
      solve satisfy;
      
      output ["The four stamp denominations were " ++
      show([d1, d2, d3, d4]) ++ " pecahans."
      ++ "\nYear 1 stamp nos (each type) = " ++ show([a, b, c, d])
      ++ "\nYear 2 stamp nos (each type) = " ++ show([e, f, g, h])
      ++ "\nYear 3 stamp nos (each type) = " ++ show([i, j, k, m]) ];
      

      Like

    • Hugo's avatar

      Hugo 12:01 pm on 26 February 2023 Permalink | Reply

      I feel it would be more logical to issue stamps worth 1, 2, 5, and 10 units.
      Then the puzzle could have stated totals of 20 and 38, together with either 21, 28, 30, or 33;
      or else 21 and 38 together with one of 22, 24, 25, 28, 29, 30, 33.
      Any of those sets would lead to a unique solution, I think.

      Like

      • Jim Randell's avatar

        Jim Randell 1:46 pm on 26 February 2023 Permalink | Reply

        That would make more sense. And the values you give do each give a unique solution with denominations of 1, 2, 5, 10.

        But perhaps the setter went with a less obvious set of denominations, so that the answer couldn’t be easily guessed.

        Like

  • Unknown's avatar

    Jim Randell 8:40 am on 16 February 2023 Permalink | Reply
    Tags:   

    Teaser 2266: Planck play 

    From The Sunday Times, 26th February 2006 [link]

    Conventional measurements are based on units of mass (M), length (L) and time (T). Any speed, such as the speed of light (c), is a length divided by a time, and we say it has “dimensions” 0 in mass, +1 in length, −1 in time. Similarly, Planck’s Constant (h) involves a mass times an area divided by time, and so has dimensions +1, +2, −1; and the Gravitation Constant (G) has dimensions −1, +3, −2. It is possible to use c, h and G respectively as the basic triplet of units. If this is done, the dimensions of the metre are −1.5, 0.5 and 0.5.

    What are those of (a) the kilogram and (b) the second?

    [teaser2266]

     
    • Jim Randell's avatar

      Jim Randell 8:41 am on 16 February 2023 Permalink | Reply

      We can write the constants (c, h, G) in terms of the dimensions (M, L, T):

            M  L  T
      c = ( 0 +1 −1)
      h = (+1 +2 −1)
      G = (−1 +3 −2)
      

      And, if we invert the matrix we can instead express the dimensions (M, L, T) in terms of (c, h, G).

      The [[ Matrix ]] class in the enigma.py library provides some useful routines for manipulating 2d matrices, including matrix inversion.

      This Python program runs in 54ms. (Internal runtime is 3.1ms).

      Run: [ @replit ]

      from enigma import (Matrix, join, printf)
      
      # matrix of (c, h, G) in terms of (M, L, T)
      m = Matrix([
        # M   L   T
        ( 0, +1, -1), # c
        (+1, +2, -1), # h
        (-1, +3, -2), # G
      ])
      
      # invert the matrix
      r = m.inv()
      
      # the dimensions (M, L, T) are the rows of the result
      for (k, ds) in zip(['kg', 'm', 's'], r.rows()):
        printf("{k} -> {ds}", ds=join(ds, sep=", ", enc="()"))
      

      Solution: The (c, h, G) dimensions are: (a) kg = (0.5, 0.5, −0.5); (b) s = (-2.5, 0.5, 0.5).

      Like

    • Hugh Casement's avatar

      Hugh Casement 2:39 pm on 16 February 2023 Permalink | Reply

      In fact since at least 2006 the speed of light has been a defined quantity,
      so that effectively the metre is defined in terms of the second.
      Since 2018 Planck’s constant has also been a defined quantity:
      was Adrian Somerfield a visionary?

      However, the Newtonian gravitational constant is known only to low precision,
      so would not make a good primary unit. And to have fractional dimensions for most of the familiar units does also not seem a good idea. Perhaps one should instead choose the Rydberg constant (inverse metres) or the related Hartree energy (joules, dimensions 1, 2, -2) for which we have very precise values.

      If I have not forgotten how to invert a matrix, we would then have (respectively)
      mass (-1, 1, 1); length ( 0, 0, -1); time (-1, 0, -1) or
      mass (-2, 0, 1); length ( 1, 1, -1); time 0, 1, 1).

      Like

  • Unknown's avatar

    Jim Randell 9:30 am on 14 February 2023 Permalink | Reply
    Tags:   

    Teaser 2717: Round the garden 

    From The Sunday Times, 19th October 2014 [link] [link]

    George and Martha’s garden is a quadrilateral with each of its sides a whole number of metres in length. When Martha wrote down the lengths of the four sides together with the length of the perimeter, she noticed that overall these five numbers used each of the ten digits exactly once. Also, the lengths of the three longest sides of the garden were prime numbers. She told George, but he was unable to work out all the lengths until she also told him that no two of the four lengths differed by a prime number.

    What are the four lengths?

    [teaser2717]

     
    • Jim Randell's avatar

      Jim Randell 9:31 am on 14 February 2023 Permalink | Reply

      This Python program finds candidate sets of sides of the quadrilateral such that the three longest sides are prime, and together with the fourth side and the calculated perimeter each of the digits 0-9 is used exactly once.

      We then check the candidate solutions for sets where no pair of lengths differ by a prime, and this gives a unique solution.

      The following Python program runs in 62ms. (Internal runtime is 11ms).

      Run: [ @replit ]

      from enigma import (primes, nsplit, irange, empty, rev, subsets, sq, printf)
      
      # combine digits of <n> with existing digits <ds>
      # digits cannot be used more than once
      def digits(n, ds):
        ds = set(ds)
        for d in nsplit(n):
          if d in ds: return
          ds.add(d)
        return ds
      
      # find sets of numbers that between them and their sum use each of the
      # 10 digits exactly once such that the largest 3 numbers are prime.
      # return: ((a, b, c, d), s); where a < b < c < d, s = a + b + c + d
      def solve(ns=[], ds=empty):
        k = len(ns)
        # are we done?
        if k == 4:
          # calculate the sum of the numbers
          t = sum(ns)
          # which should bring the digits used to 10
          ds_ = digits(t, ds)
          if ds_ is not None and len(ds_) == 10:
            yield (rev(ns), t)
        else:
          # first 3 numbers are primes, but final number is not necessarily a prime
          a = 1
          b = (111 if k == 0 else ns[-1] - 1)
          nrange = (irange if k == 3 else primes.irange)
          for n in nrange(a, b):
            # check for new distinct digits
            ds_ = digits(n, ds)
            if ds_ is not None:
              yield from solve(ns + [n], ds_)
      
      # quadrilateral check
      def is_quad(ss):
        if len(ss) != 4: return
        (a, b, c, d) = ss
        # a + b + c > d
        if not (a + b + c > d): return
        # a^2 + b^2 + c^2 > d^2 / 3
        (a2, b2, c2, d2) = map(sq, (a, b, c, d))
        if 3 * (a2 + b2 + c2) <= d2: return
        # a^4 + b^4 + c^4 >= d^4 / 27
        (a4, b4, c4, d4) = map(sq, (a2, b2, c2, d2))
        if 27 * (a4 + b4 + c4) < d4: return
        # looks OK
        return 1
      
      # difference check: no pair of lengths differs by a prime
      diff = lambda ss: not any(primes.is_prime(y - x) for (x, y) in subsets(ss, size=2))
      
      # collect possible sides and perimeters
      for (ss, p) in solve():
        if not is_quad(ss): continue
        # apply difference check
        d = diff(ss)
        printf("{ss} -> {p}; diff = {d}")
      

      Solution: The sides of the quadrilateral are (in metres): 4, 53, 61, 89.

      And the perimeter is 207 m:

      4 + 53 + 61 + 89 = 207

      Without the additional condition that no two of the lengths differ by a prime number there is a second candidate solution:

      4 + 59 + 61 + 83 = 207

      But this fails the difference test (as: 83 − 4 = 79, and 61 − 59 = 2, both of which are primes).


      If we assume the garden is a convex quadrilateral, then the length 4 side is considerably shorter than the other 3 sides, so the shape of the garden is roughly a (59, 61, 83) triangle.

      We can take this triangle and “open out” two of the sides until we have introduced a gap of 4 between them. To give us shapes like this:

      Like

    • GeoffR's avatar

      GeoffR 4:36 pm on 14 February 2023 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      predicate is_prime(var int: x) = 
      x > 1 /\ forall(i in 2..1 + ceil(sqrt(int2float(ub(x))))) 
      ((i < x) -> (x mod i > 0));
      
      % Digits for quadrilateral sides and perimeter
      % Assumed sides are A, BC, DE, FG and HIJ for the ten digits
      var 1..9:A; var 1..9:B; var 1..9:C; var 1..9:D;
      var 1..9:E; var 1..9:F; var 1..9:G; var 0..9:H;
      var 0..9:I; var 1..9:J;
      
      % The ten digits are used exactly once
      constraint all_different([A, B, C, D, E, F, G, H, I, J]);
      
      % Ordering values of quadrilateral sides
      constraint A < BC /\ BC < DE /\ DE < FG;
      
      % Quadrilateral sides are, A, BC, DE, FG
      var 10..99:BC = 10*B + C;
      var 10..99:DE = 10*D + E;
      var 10..99:FG = 10*F + G;
      constraint A + BC + DE > FG;
      
      % Perimeter of quadrilateral
      var 100..999: HIJ = 100*H + 10*I + J;
      constraint HIJ = A + BC + DE + FG;
      
      % Three largest sides of the quadrilateral are prime
      constraint is_prime(BC) /\ is_prime(DE) /\ is_prime(FG);
      
      % No two sides differ by a prime number
      constraint sum( [is_prime(BC - A), is_prime(DE - A), is_prime(FG - A),
      is_prime(DE - BC), is_prime(FG - BC), is_prime(FG - DE)]) == 0;
      
      solve satisfy;
      
      output ["[A, BC, DE, FG, HIJ] = " ++ show([A, BC, DE, FG, HIJ]) ];
      
      % [A, BC, DE, FG, HIJ] = [4, 53, 61, 89, 207]
      % ----------
      % ==========
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:34 am on 12 February 2023 Permalink | Reply
    Tags: ,   

    Brain-Teaser 931: Seven primes for seven brothers 

    From The Sunday Times, 25th May 1980 [link]

    Large families often have problems, particularly when it comes to deciding who has first choice, etc.

    My six brothers and I solved this particular one by devising our own dice game. Each of us in turn would roll a die four times and put the results together in that order to form a four-figure number. (So that, for example: 6 followed by 2, then 3 and 1, gives the number 6231). We would each do this and the one of us getting the highest four-figure number would be declared the winner.

    One such game had some very strange results. Each of us got a different prime number, using the same four different digits. The average of the seven primes was a perfect square, to which Jon’s number was the nearest.

    The difference between Ron’s and Don’s numbers, multiplied by one of the numbers from the die, gave the difference between Len’s and Ken’s numbers.

    Omitting Ben’s score, the total could have been formed by throwing the die five times. And so could the total of the numbers thrown by Len, Ken, Ron and me.

    What was my score, and who ate the biggest piece of apple pie?

    The originally published version of this puzzle was flawed, so the version above was taken from the book Microteasers (1986), in which it was noted:

    There is an interesting postscript to [this] puzzle. When it first appeared, the condition “each of us got a different prime number using the same four different digits” was given as “each of us got a different prime number; two digits never came up”. That allowed numbers like 5651, which was not the intention at all. The odd thing is that all the readers who sent in answers found the intended solution anyway. So perhaps, even if one relaxes the condition about all the primes using four different digits, the teaser still has a unique solution. The keener reader might like to adapt the program to take four digits in turn and see how many primes can be made from those four (but not necessarily using all four each time). Then you have to consider all possible sets of seven from those. We leave this much harder problem as an exercise.

    However the original formulation of the puzzle does not give a unique solution.

    [teaser931]

     
    • Jim Randell's avatar

      Jim Randell 8:36 am on 12 February 2023 Permalink | Reply

      The original formulation of the puzzle is flawed, so I used the version from the Microteasers (1986) book.

      The following Python program runs in 58ms. (Internal runtime is 1.2ms).

      Run: [ @replit ]

      from enigma import (irange, primes, nconcat, nsplit, subsets, div, is_square, diff, printf)
      
      # digits on a die
      digits = set(irange(1, 6))
      
      # check the numbers <ns> form a valid solution
      def check(ns):
        # total must be > 4-digit
        t = sum(ns)
        if t < 10000: return
        mx = max(ns)
        # calculate the mean
        m = div(t, len(ns))
        if m is None or not is_square(m): return
        # J is the closest to the mean
        fn = lambda n: abs(n - m)
        ns = sorted(ns, key=fn)
        J = ns.pop(0)
        if not fn(J) < fn(ns[0]): return
        # choose R, D values
        for (R, D) in subsets(ns, size=2):
          d = abs(R - D)
          # find another pair that is a multiple of d for L, K
          for (L, K) in subsets(diff(ns, {R, D}), size=2):
            x = div(abs(L - K), d)
            if x not in digits: continue
            # remaining pair are B and M
            for (B, M) in subsets(diff(ns, {R, D, L, K}), size=2, select="P"):
              # total less B can be expressed with 5 dice
              ds = nsplit(t - B)
              if not (len(ds) == 5 and digits.issuperset(ds)): continue
              # as can L + K + R + M
              for (R_, D_) in [(R, D), (D, R)]:
                ds = nsplit(L + K + R_ + M)
                if not (len(ds) == 5 and digits.issuperset(ds)): continue
                # output solution
                printf("J={J} R={R_} D={D_} L+K={L}+{K} B={B} M={M} [m={m} d={d} x={x}]")
                n2t = { J: 'Jon', R_: 'Ron', D_: 'Don', L: '{LK}en', K: '{KL}en', B: 'Ben', M: 'Me'}
                printf("-> Me = {M}; max = {mx}", mx=n2t[mx])
      
      # only 4 digits are used
      for ds in subsets(digits, size=4, fn=set):
        # collect possible primes
        ps = list(n for n in subsets(ds, size=len, select="P", fn=nconcat) if primes.is_prime(n))
        # choose 7 of the primes
        for ns in subsets(ps, size=7):
          # and check for a solution
          check(ns)
      

      Solution: The setter scored 4153. And Don got the highest score.

      There is only one set of 4 dice digits that can form 7 primes, and this set gives exactly seven primes, so we just need to distribute them amongst the brothers according to the given conditions.

      The scores are:

      Len = 1543
      Ken = 1453
      Jon = 3541
      Me = 4153
      Ben = 4513
      Ron = 5413
      Don = 5431

      (Although Ken and Len can swap scores and still give a valid solution).

      The mean value is: 3721 = 61², and Jon has the closest value to this.

      The difference between Ron and Don is 18. And the difference between Len and Ken is 90 = 5 × 18.

      The total without Ben is 21534, which uses 5 dice digits.

      The total of Len, Ken, Ron and Me is 12562, which also uses 5 dice digits.


      However, with the formulation of the puzzle (as originally published in The Sunday Times) there are many further solutions, which the program above can be adapted to find.

      For example, the following primes use only the digits: 1, 3, 5, 6:

      Ben = 1151
      Jon = 5153
      Len = 5651
      Ron = 6133
      Ken = 6311
      Don = 6353
      Me = 6551

      The mean value is: 5329 = 73², and Jon has the closest value to this.

      The difference between Ron and Don is 220. And the difference between Len and Ken is 660 = 3 × 220.

      The total without Ben is: 36152, which uses 5 dice digits.

      The total of Len, Ken, Ron and Me is: 24646, which also uses 5 dice digits.

      And in this case the answer would be that the setters score is 6551, and this is also the highest of the scores.

      Like

    • Hugh Casement's avatar

      Hugh Casement 7:15 pm on 13 February 2023 Permalink | Reply

      There are only 32 four-digit primes that use just the digits 1 to 6 with no repeat.
      And the subset forming the solution to this puzzle is the only one with seven members.
      There is one with six members: 1523, 2153, 2351, 2531, 3251, 5231.
      I haven’t tried constructing a puzzle with those numbers.

      Like

    • GeoffR's avatar

      GeoffR 8:50 am on 15 February 2023 Permalink | Reply

      I found the 32 no. 4-digit primes and divided them into sets of primes with the same 4 digits. For a dice range of (1..6), all primes must end in 1 or 3.

      There was 1 set of 7 primes, 1 set of 6 primes, 2 sets of 4 primes, 2 sets of 3 primes, 2 sets of 2 primes, and 1 set of 1 prime.

      {4231, 2341, 2143, 1423}
      {4513, 5413, 1543, 1453, 3541, 5431, 4153} – 7 no. primes in this set
      {2531, 2153, 2351, 5231, 1523, 3251}
      {4523, 4253, 2543}
      {3461, 6143}
      {6421, 4621, 4261}
      {4561, 4651, 6451, 5641}
      {6521, 5261}
      {5623}

      % A Solution in MiniZinc
      include "globals.mzn";
      
      set of int : primes = {4513, 5413, 1543, 1453, 3541, 5431, 4153};
      
      var primes: Len; var primes: Ken; var primes: Jon; var primes: Me;
      var primes: Ben; var primes: Ron; var primes: Don;
      
      constraint all_different([Len, Ken, Jon, Me, Ben, Ron, Don]);
      
      predicate is_sq(var int: y) =
      exists(z in 1..ceil(sqrt(int2float(ub(y))))) (z*z = y );
      
      % The average of the seven primes was a perfect square.
      constraint is_sq((4513 + 5413 + 1543 + 1453 + 3541 + 5431 + 4153) div 7);
      var 3000..4000: average = (4513 + 5413 + 1543 + 1453 + 3541 + 5431 + 4153) div 7;
      
      % The difference between Ron’s and Don’s numbers, multiplied by one of the numbers
      % from the die, gave the difference between Len’s and Ken’s numbers.
      var 1..300:d1; var 1..6:m;  % difference d1 and multiplier m from dice values.
      
      constraint abs (Ron - Don) == d1;
      constraint d1 * m == (Len - Ken);
      
      % The total without Ben uses 5 dice digits.
      var int: total = 4513 + 5413 + 1543 + 1453 + 3541 + 5431 + 4153; 
      
      var 20000..26000: tot_minus_Ben = total - Ben;
      
      % Digits of (total - Ben)
      var 1..6:a; var 1..6:b; var 1..6:c; var 1..6:d; var 1..6:e;
      
      constraint tot_minus_Ben div 10000 == a /\ a in {1,2,3,4,5,6};
      constraint tot_minus_Ben div 1000 mod 10 == b /\ b in {1,2,3,4,5,6};
      constraint tot_minus_Ben div 100 mod 10 == c /\ c in {1,2,3,4,5,6};
      constraint tot_minus_Ben div 10 mod 10 == d /\ d in {1,2,3,4,5,6};
      constraint tot_minus_Ben mod 10 == e /\ e in {1,2,3,4,5,6};
      
      % The total of Len, Ken, Ron and Me also uses 5 dice digits.
      var 1..6:f; var 1..6:g; var 1..6:h; var 1..6:i; var 1..6:j;
      
      var 12000..20000: LKRMe = Len + Ken + Ron + Me;
      
      constraint LKRMe div 10000 == f /\ f in {1,2,3,4,5,6};
      constraint LKRMe div 1000 mod 10 == g /\ g in {1,2,3,4,5,6};
      constraint LKRMe div 100 mod 10 == h /\ h in {1,2,3,4,5,6};
      constraint LKRMe div 10 mod 10 == i /\ i in {1,2,3,4,5,6};
      constraint LKRMe mod 10 == j /\ j in {1,2,3,4,5,6};
      
      solve minimize( abs(Jon - average));
      
      output ["[Len, Ken, Jon, Me, Ben, Ron, Don] = " 
      ++ show([Len, Ken, Jon, Me, Ben, Ron, Don]) 
      ++ "\n" ++ "[a,b,c,d,e ] = " ++ show( [a,b,c,d,e] )
      ++ "\n" ++ "[f,g,h,i,j ] = " ++ show( [f,g,h,i,j] ) 
      ++ "\n" ++ "Average = " ++ show(average)];
      
      % [Len,   Ken, Jon,   Me,   Ben, Ron,  Don] = 
      % [1543, 1453, 3541, 4153, 4513, 5413, 5431]
      % [a,b,c,d,e ] = [2, 1, 5, 3, 4]
      % [f,g,h,i,j ] = [1, 2, 5, 6, 2]
      % Average = 3721
      % ----------
      % ==========
      
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:36 pm on 10 February 2023 Permalink | Reply
    Tags:   

    Teaser 3151: Plant stock 

    From The Sunday Times, 12th February 2023 [link] [link]

    A garden centre bought 500 plants of four different varieties from its supplier. The price per plant of each variety was a whole number of pence and their total average price worked out at exactly one pound.

    The number of plants of variety 2 purchased was “d” greater than that of variety 1, and its price per plant was “d” pence less than that of variety 1. Similarly, the number of variety 3 plants equalled the number of variety 2 plus “d” and its price equalled the variety 2 price less “d” pence. Finally, the number of variety 4 plants equalled the number of variety 3 plus “d” and its price equalled the variety 3 price less “d” pence.

    What, in pence, is the most that a plant could have cost?

    [teaser3151]

     
    • Jim Randell's avatar

      Jim Randell 4:57 pm on 10 February 2023 Permalink | Reply

      If there were n plants of variety 1 bought at a price of p pence per plant, then we have the following plants bought:

      variety 1: n @ p
      variety 2: (n + d) @ (p − d)
      variety 3: (n + 2d) @ (p − 2d)
      variety 4: (n + 3d) @ (p − 3d)

      In total there were (4n + 6d) = 500 plants bought.

      For a given n we can calculate d (which needs to be an integer):

      d = (500 − 4n) / 6

      And the mean cost per plant was 100 pence, so the total cost of 500 plants was 50000 pence. And so we can calculate p (which also needs to be an integer):

      n.p + (n + d)(p − d) + (n + 2d)(p − 2d) + (n + 3d)(p − 3d) = 50000
      500p = 50000 + d(n + d) + 2d(n + 2d) + 3d(n + 3d)
      p = (50000 + d(14d + 6n)) / 500

      from enigma import (irange, div, printf)
      
      # consider the number of var 1 plants bought
      for n in irange(1, 124):
        d = div(500 - 4 * n, 6)
        if d is None: continue
      
        # find the price that makes the mean exactly 100
        p = div(50000 + d * (14 * d + 6 * n), 500)
        if p is None: continue
        printf("n={n} -> d={d} p={p}")
        break
      

      Solution: The maximum possible price for a plant is 284p.

      And for this value of p we have:

      n = 5; d = 80; p = 284

      variety 1: 5 plants @ 284 p each = £14.20
      variety 2: 85 plants @ 204 p each = £173.40
      variety 3: 165 plants @ 124 p each = £204.60
      variety 4: 245 plants @ 44 p each = £107.80
      total = 500 plants, £500.


      Manually:

      The equation for p can be simplified to:

      p = (d² + 150d + 10000) / 100
      p = d²/100 + 3d/2 + 100

      So d must be a multiple of 10, say d = 10k:

      p = k² + 15k + 100
      n = 125 − 15k

      We maximise p by maximising k, and the largest value k can take (keeping n positive) is 8, giving:

      k = 8
      d = 80
      n = 5
      p = 284
      quantities = (5, 85, 165, 245)
      prices = (284, 204, 124, 44)

      Like

    • GeoffR's avatar

      GeoffR 9:31 am on 12 February 2023 Permalink | Reply

      
      # Using Jim's analysis
      PL = []  # list to store plant costs
      
      for n in range(1, 123):
        for d in range(1, 83):
          if 4*n + 6*d == 500:
            d = (500 - 4*n) // 6
            for p in range(1, 350):
              if 500*p == 50000 + d *(14*d + 6*n):
                PL.append(p)
      
      # Find maximum plant price
      print(f"Maximum plant price = {max(PL)} pence.")
      
      

      Like

  • Unknown's avatar

    Jim Randell 9:14 am on 7 February 2023 Permalink | Reply
    Tags: ,   

    Teaser 2692: Runners-up 

    From The Sunday Times, 27th April 2014 [link] [link]

    In our local football league each team plays each other team twice each season, once at home and once away. The teams get three points for a win and one point for a draw. All games are on Saturdays at 3pm, and yesterday all the teams played their last game, so the final league table has now been published. Our team were runners-up, but we should have won! We were just one point behind the winners and, although they won two-thirds of their games, our team won more. Furthermore, looking at our drawn games, I notice that the league winners lost twice as many games as we drew.

    How many games did the league winners win, draw and lose?

    [teaser2692]

     
    • Jim Randell's avatar

      Jim Randell 9:15 am on 7 February 2023 Permalink | Reply

      This puzzle should have been worded more carefully to eliminate multiple solutions.

      If there are n teams in the league, then each team plays each of the other (n − 1) teams both at home and away, so each team plays (2n − 2) matches.

      The fact that all teams can play at one time tells us that n must be even (so the teams can all be paired up).

      We are not told how long the season is, but if we suppose that it lasts less than 1 year, then as the teams play 1 match per week, we can suppose than n ≤ 26 (otherwise it would not be possible to fit all the matches in).

      I am assuming that “the league winners lost twice as many games as we drew” implies that the numbers involved are non-zero (otherwise it would be a bit of an odd way to phrase it), but this does not give a unique solution.

      The following Python program runs in 52ms. (Internal runtime is 190µs).

      Run: [ @replit ]

      from enigma import (irange, inf, div, printf)
      
      # consider number of teams in the league (must be even)
      for n in irange(2, inf, step=2):
        # total number of matches played by each team
        played = 2 * (n - 1)
        if played > 52: break
        # the winners won 2/3 of their matches
        w1 = div(2 * played, 3)
        if w1 is None: continue
      
        # consider the number of draws for the runners up (at least 1)
        for d2 in irange(1, played):
          # the winners lost twice this amount
          l1 = 2 * d2
          # calculate the draws and points for the winners
          d1 = played - w1 - l1
          if d1 < 0: break
          pts1 = 3 * w1 + d1
          # calculate the points, wins for the runners up
          pts2 = pts1 - 1
          w2 = div(pts2 - d2, 3)
          if w2 is None or not (w2 > w1): continue
          l2 = played - w2 - d2
          if l2 < 0: continue
          # some sanity checks
          if not (w1 + l2 < played - 2 and w2 + l1 < played - 2): continue
          # output solution
          printf("n={n} d2={d2}: played={played}; (w, d, l, pts) #1 ({w1}, {d1}, {l1}, {pts1}); #2 ({w2}, {d2}, {l2}, {pts2})")
      

      There are two candidate solutions:

      16 teams in the league; each team plays 30 matches.

      winners: w=20, d=8, l=2, pts=68; runners up: w=22, d=1, l=7, pts=67
      winners: w=20, d=6, l=4, pts=66; runners up: w=21, d=2, l=7, pts=65

      The published answer (“20, 6 and 4”) corresponds to the second of these scenarios.

      It has been suggested that “looking at our drawn games” necessarily implies that the runners-up must have more than one drawn match (eliminating the first of the above solutions), but I think if this was the intention a clearer choice of words would be necessary.

      Like

  • Unknown's avatar

    Jim Randell 11:06 am on 5 February 2023 Permalink | Reply
    Tags:   

    Brain-Teaser 180: [Crates of books] 

    From The Sunday Times, 20th September 1964 [link]

    A publisher dispatches crates of mixed books to retailers — Adventure (high price), Biography (medium price), and Crime (low price). The crates each contain an equal number of books, but, conforming to local tastes, all have different proportions of the three books, and in fact, within the invoice price of £54 per crate it takes exactly every possible combination of the three to supply his customers.

    On taking stock he finds that to each 2 of A, he has sold 3 each of B and C.

    Weeks later, to the same customers, and under the same conditions, he despatches a similar consignment, except that on this occasion the three books have a wider price range. One of the crates, however, is mistakenly packed in proportion: A:B:C = 4:3:2, instead of A:B:C = 3:2:4.

    What is the true total value of this consignment?

    (All book prices are exact shillings).

    This puzzle was originally published with no title.

    [teaser180]

     
    • Jim Randell's avatar

      Jim Randell 11:07 am on 5 February 2023 Permalink | Reply

      When the solution was published it was noted: “Only 43 attempted this “fifth-form” Brain-teaser (180) and only 15 accurately solved it”.

      However I did find it was necessary to add the following conditions to arrive at a unique solution:

      (1) there is at least 1 copy of each type of book in each crate; and:
      (2) there are at least 3 crates in each consignment

      The two consignments are to the same customers, so presumably consist of the same number of crates, the same number of books per crate, the same value per crate, and the same distribution of books per crate.

      Each crate contains books to a value of £54. At 20 shillings per pound this is 1080 shillings. (All following values are given in shillings).

      Each create contains the same number of books say n, and the incorrectly packed crate is meant to be packed with books in the ratio A:B:C = 3:2:4, so n must be a multiple of 9 (say 9k).

      So, given a value for n, we can determine the how many of each book are meant to be in the incorrectly packed crate, and consider prices that give the crate a total value of 1080. Then using these prices we can determine how many different packings there are (assuming at least 1 book of each type per crate), which gives us the total number of crates in each consignment. (And at this point I also found it necessary to assume that there were at least 3 crates in a consignment). We can then determine the total number of books of each type in the entire consignment, and check that these are in the ratio A:B:C = 2:3:3.

      From these potential prices and packings we can select two candidates, one with a narrower range of prices and one with a wider range of prices. And we can then calculate the actual value of the incorrectly packed crate in the consignment with the wider price range to give the required answer.

      This Python program runs in 1.91s.

      Run: [ @replit ]

      from enigma import (irange, inf, div, express, rev, unpack, unzip, ratio, subsets, printf)
      
      # construct prices (pA, pB, pC), such that: pA > pB > pC, for
      # quantities of books (nA, nB, nC) with a total value of t
      def prices(nA, nB, nC, t):
        # choose a price for the most expensive books
        for pA in irange(3, inf):
          r1 = t - pA * nA
          if r1 < 0: break
          # choose a price for the cheapest books
          for pC in irange(1, pA - 2):
            r2 = r1 - pC * nC
            if r2 < 0: break
            # calculate the price of the mid-prices books
            pB = div(r2, nB)
            if pB and pA > pB > pC:
              yield (pA, pB, pC)
      
      # construct numbers of books (nA, nB, nC) priced at (pA, pB, pC)
      # such that: nA + nB + nC = n, and the total value of the crate is t
      def crates(n, pA, pB, pC, t):
        for qs in express(t, [pC, pB, pA], min_q=1):
          if sum(qs) == n:
            yield rev(qs)
      
      # consider the number of books per crate (is a multiple of 9, say 9k)
      for k in irange(1, 63):
        # number of intended books in the incorrectly packed crate
        (nA, nB, nC) = (3 * k, 2 * k, 4 * k)
        n = nA + nB + nC
      
        # find possible prices, sorted by price range (narrow to wide)
        ps = list(prices(nA, nB, nC, 1080))
        # we need at least 2 different prices
        if len(ps) < 2: continue
      
        # for each set of prices consider all possible crate packings
        # and record those that give total numbers of books in the consigment
        # in the ratio A:B:C = 2:3:3
        rs = list()
        for (pA, pB, pC) in ps:
          # find all possible crate packings
          cs = list(crates(n, pA, pB, pC, 1080))
          if len(cs) < 3: continue  # require at least 3 different packings
          # sum the total numbers of books in the consignment
          (tA, tB, tC) = map(sum, unzip(cs))
          if ratio(tA, tB, tC) == (2, 3, 3):
            rs.append((pA, pB, pC, cs))
        if len(rs) < 2: continue
      
        # sort results by price range (narrow to wide)
        prange = unpack(lambda pA, pB, pC, cs: pA - pC)
        rs.sort(key=prange)
      
        # choose pairs with narrow and wide price ranges
        for (nr, wr) in subsets(rs, size=2):
          if not prange(nr) < prange(wr): continue
          # output solution
          printf("{n} books per crate")
          for (i, (pA, pB, pC, cs)) in enumerate((nr, wr), start=1):
            printf("[consignment {i}] prices (A, B, C) = ({pA}, {pB}, {pC})")
            tv = 0
            for (nA, nB, nC) in cs:
              v = nA * pA + nB * pB + nC * pC
              printf("-> crate (A, B, C) = ({nA}, {nB}, {nC}); value = {v}")
              if i == 2 and ratio(nA, nB, nC) == (3, 2, 4):
                v = nC * pA + nA * pB + nB * pC
                printf("--> packed as (A, B, C) = ({nC}, {nA}, {nB}); value = {v}")
              tv += v
            printf("total value of consignment = {tv}")
            printf()
      

      Solution: The total value of the second consignment is 5672s (= £283 + 12s).


      If the books are priced: A=21, B=16, C=10, then with 72 books per crate, we can make the following (A, B, C) crates contain books with a value of 1080s:

      (6, 49, 17)
      (12, 38, 22)
      (18, 27, 27)
      (24, 16, 32) [*]
      (30, 5, 37)

      The total number of books of each type in the consignment is (90, 135, 135) which are in the ratio 2:3:3.

      And the indicated crate [*] has books in the ratio 3:2:4.

      The total value of the shipment is 5× 1080 = 5400.

      If the prices of the books are subsequently changed to: A=27, B=17, C=5 (a wider price range), then the same set of crates can be made, and each crate still contains 72 books with a value of 1080.

      But in the second consignment the 72 books in the starred crate [*] are incorrectly packed as (32, 24, 16).

      Meaning there are 8 more copies of A, 8 more copies of B, and 16 fewer copies of C.

      So the actual total value of the second shipment is: 8×27 + 8×17 − 16×5 = 272 more than before, i.e. 5400 + 272 = 5672.


      Without the requirement that there are at least 3 crates in a shipment we can find additional solutions, such as:

      36 books per crate
      [consignment 1] prices (A, B, C) = (36, 31, 25)
      → crate (A, B, C) = (6, 19, 11); value = 1080
      → crate (A, B, C) = (12, 8, 16); value = 1080
      total value of consignment = 2160

      [consignment 2] prices (A, B, C) = (42, 32, 20)
      → crate (A, B, C) = (6, 19, 11); value = 1080
      → crate (A, B, C) = (12, 8, 16); value = 1080
      → → packed as (A, B, C) = (16, 12, 8); value = 1216
      total value of consignment = 2296

      Which may account for some of the incorrect entries received at the time.

      Like

  • Unknown's avatar

    Jim Randell 4:34 pm on 3 February 2023 Permalink | Reply
    Tags:   

    Teaser 3150: Pyramids of Wimbledon 

    From The Sunday Times, 5th February 2023 [link]

    Edward, the sports shop owner, had an annual display of tennis balls. He arranged the balls in four identical pyramids, with a square base holding each in place (one ball on the top of each pyramid, four on the layer below, nine below that and so on).

    However, this year he wanted to display the same number of balls but reduce the total footprint of the bases by at least 55 per cent, to allow for other stock. His son Fred suggested arranging all the balls in one large pyramid with an equilateral triangular base (one ball on the top, three on the layer below, six below that and so on). Edward realised that this would work, but if there were any fewer balls, it wouldn’t work.

    How many balls did Edward display?

    [teaser3150]

     
    • Jim Randell's avatar

      Jim Randell 5:21 pm on 3 February 2023 Permalink | Reply

      I took the footprint of the base to be the area of the enclosing polygon (so a square for the square based pyramids, and an equilateral triangle for the tetrahedral pyramids). And we are looking for a reduction of at least 55%, so the footprint of the tetrahedral pyramid must be not more than 45% that of the total footprint of the four square based pyramids.

      This Python program finds the solution constructively. It runs in 53ms. (Internal runtime is 134µs).

      Run: [ @replit ]

      from enigma import (sqrt, sq, tri, fdiv, printf)
      
      r3 = sqrt(3)
      
      # generate pyramid numbers, base defined by <fn>
      def pyramid(fn):
        n = 0  # number of layers
        b = 0  # number of balls in base
        t = 0  # total number of balls
        while True:
          yield (n, b, t)
          n += 1
          b = fn(n)
          t += b
      
      sq_pyr = pyramid(sq)  # square pyramidal numbers
      tri_pyr = pyramid(tri)  # tetrahedral numbers
      
      # find number of layers for a tetrahedral pyramid
      (cache, max_tt) = (dict(), -1)
      
      # consider number of balls in a square based pyramid
      for (sn, sb, st) in sq_pyr:
        # the puzzle text implies there are at least 3 layers
        if sn < 3: continue
        # total number of balls in the 4 square based pyramids
        t = 4 * st
      
        # can we find a tetrahedral number with t balls?
        while max_tt < t:
          (tn, tb, tt) = next(tri_pyr)
          cache[tt] = (tn, tb, tt)
          max_tt = tt
        rs = cache.get(t)
        if rs is None: continue
        (tn, tb, tt) = rs
      
        # calculate the ratio of the footprints (= enclosing polygons)
        f = fdiv(0.25 * r3 * sq(tn + r3 - 1), 4 * sq(sn))
        if f > 0.45: continue
        # output solution
        printf("4x {sn}-layer SP = {t} balls -> 1x {tn}-layer tetra [f = {f:0.3f}]")
        break
      

      Solution: The display consisted of 9880 balls.

      Each square pyramid consisted of 19 layers, giving 2470 balls, and altogether the 4 pyramids use 9880 balls.

      The single tetrahedral pyramid has 38 layers, which also uses 9880 balls.


      Analytically:

      The formulae for the square pyramidal numbers (SP[n]) and tetrahedral numbers (Te[n]) are:

      SP[n] = n(n + 1)(2n + 1)/6
      Te[n] = n(n + 1)(n + 2)/6

      And we see:

      Te[2n] = 2n(2n + 1)(2n + 2)/6
      Te[2n] = 4 n(n + 1)(2n + 1)/6
      Te[2n] = 4 SP[n]

      So we are looking for the smallest value where the footprint of Te[2n] is not more than 0.45 the footprint of 4× SP[n].

      The footprints can be calculated as follows:

      fpSP(n) = n²
      fpTe(n) = (n + √3 − 1)² (√3/4)

      Hence:

      fpTe(2n) / 4.fpSP(n) ≤ f
      (√3 − 1) / n ≤ r − 2; where: r = 4 √(f / √3)
      n = ceil((√3 − 1) / (r − 2))

      For f = 0.45 we get n = 19.

      So the answer occurs with 4 square based pyramids with 19 layers, or 1 tetrahedral pyramid with 38 layers.

      Each display uses 9880 balls.

      Like

  • Unknown's avatar

    Jim Randell 11:37 am on 2 February 2023 Permalink | Reply
    Tags:   

    Teaser 2704: Celebrity gardeners 

    From The Sunday Times, 20th July 2014 [link] [link]

    There were six celebrity gardeners at the local show:

    Beardshaw, Dimmock, Flowerdew, Greenwood, Klein, Thrower.

    Each of them was exhibiting two different shrubs from the following list:

    Abutilon, Azalea, Berberis, Cornus, Euonymus, Hibiscus, Holly, Magnolia, Potentilla, Spiraeas, Weigela, Wisteria.

    On each of six tables there was a card containing the gardener’s surname and the name of the two shrubs. For any two of the words on the same card, there were exactly two letters of the alphabet that occurred (perhaps more than once) in both.

    (a) Which two shrubs did Beardshaw exhibit?

    (b) Who exhibited the Abutilon?

    [teaser2704]

     
    • Jim Randell's avatar

      Jim Randell 11:37 am on 2 February 2023 Permalink | Reply

      We can solve this puzzle using the [[ grouping ]] solver from the enigma.py library.

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

      Run: [ @replit ]

      from enigma import grouping
      
      names = ('Beardshaw', 'Dimmock', 'Flowerdew', 'Greenwood', 'Klein', 'Thrower')
      
      plants = (
        'Abutilon', 'Azalea', 'Berberis', 'Cornus', 'Euonymus', 'Hibiscus',
        'Holly', 'Magnolia', 'Potentilla', 'Spiraeas', 'Weigela', 'Wisteria',
      )
      
      # form the 2-gangs
      for gs in grouping.gangs(2, names, plants, grouping.share_letters(2)):
        # output the groups
        grouping.output_gangs(names, gs)
      

      Solution: (a) Beardshaw exhibited: Cornus, Potentilla. (b) Abutilon was exhibited by Greenwood.

      Like

  • Unknown's avatar

    Jim Randell 11:22 am on 31 January 2023 Permalink | Reply
    Tags:   

    Teaser 2718: By the dozen 

    From The Sunday Times, 26th October 2014 [link] [link]

    I have written down a five-figure number that uses five different non-zero digits, and then I have replaced the digits by letters to give DOZEN. Within this it is possible to see various numbers, namely:

    D, O, Z, E, N
    DO, OZ, ZE, EN
    DOZ, OZE, ZEN
    DOZE, OZEN
    DOZEN

    Surprisingly, the original number is divisible by a dozen or more of these.

    What is the number DOZEN?

    [teaser2718]

     
    • Jim Randell's avatar

      Jim Randell 11:23 am on 31 January 2023 Permalink | Reply

      Of the 15 fragments, there can be at most 3 of them that do not divide into DOZEN, and we don’t need to check that DOZEN divides into itself, so we just need to check that at most 3 of the fragments of length 1 to 4 do not.

      This Python program runs in 193ms. (Internal runtime is 92ms).

      Run: [ @replit ]

      from enigma import (irange, tuples, nconcat, subsets, icount_at_most, printf)
      
      # construct fragments of sequence <seq>, of size <ks>
      def fragments(seq, ks):
        for k in ks:
          for t in tuples(seq, k):
            yield t
      
      # consider 5 different digits
      for ds in subsets(irange(1, 9), size=5, select="P"):
        n = nconcat(ds)
        # fragments of length 1-4
        fs = fragments(ds, irange(1, 4))
        # at most 3 of the fragments do not divide into n
        fn = lambda ds: n % nconcat(ds) != 0
        if icount_at_most(fs, fn, 3):
          # output solution
          printf("DOZEN = {n}")
      

      Solution: DOZEN = 31248.

      There are 3 fragments that do not divide 31248. These are: 312, 3124, 1248.

      And the remaining 12 fragments do divide 31248.

      Like

    • GeoffR's avatar

      GeoffR 1:55 pm on 31 January 2023 Permalink | Reply

      As a contrast, I checked for eleven fragments which do divide the five digit number.
      With the five digit number itself, this is equivalent to twelve divisions. I did not consider it necessary check for more than twelve divisions.

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:D; var 1..9:O; var 1..9:Z; var 1..9:E; var 1..9:N;
      
      constraint all_different([D, O, Z, E, N]);
      
      var 10..99:DO = 10*D + O;
      var 10..99:OZ = 10*O + Z;
      var 10..99:ZE = 10*Z + E;
      var 10..99:EN = 10*E + N;
      var 100..999:DOZ = 100*D + 10*O + Z;
      var 100..999:OZE = 100*O + 10*Z + E;
      var 100..999:ZEN = 100*Z + 10*E + N;
      var 1000..9999: DOZE = 1000*D + 100*O + 10*Z + E;
      var 1000..9000: OZEN = 1000*O + 100*Z + 10*E + N;
      var 10000..99999:DOZEN = 10000*D + 1000*O + 100*Z + 10*E + N;
      
      
      % % DOZEN divides itself, so only 11 fragment divisions to check
      constraint sum  
        ([DOZEN mod D == 0, DOZEN mod O == 0, DOZEN mod Z == 0,
          DOZEN mod E == 0, DOZEN mod N == 0, DOZEN mod DO == 0,
          DOZEN mod OZ == 0,DOZEN mod ZE == 0, DOZEN mod EN == 0,
          DOZEN mod DOZ == 0,DOZEN mod OZE == 0,DOZEN mod ZEN == 0,
          DOZEN mod DOZE == 0, DOZEN mod OZEN == 0]) == 11;
                       
      solve satisfy;
      
      output ["DOZEN = " ++ show(DOZEN) ];
                       
      % DOZEN = 31248
      % ----------
      % ==========
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:49 pm on 29 January 2023 Permalink | Reply
    Tags:   

    Teaser 2277: Round the front 

    From The Sunday Times, 14th May 2006 [link]

    George and Martha’s telephone number has just changed. It consists of the same six non-zero digits as before, but the two-figure number formed by the last two digits has been chopped off and moved to the front. The effect of this move is that their new number is precisely four times their old one.

    What is their new number?

    [teaser2277]

     
    • Jim Randell's avatar

      Jim Randell 4:50 pm on 29 January 2023 Permalink | Reply

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

      The following run file executes in 199ms. (Internal run time of the generated program in 25ms).

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      --digits="1-9"
      --distinct=""
      
      "4 * ABCDEF = EFABCD"
      

      Solution: The new number is: 571428.

      The old number is the repetend of 1/7, and the new number is the repetend of 4/7.

      1/7 = 0.(142857)…
      4/7 = 0.(571428)…


      For a faster program we can use the [[ SubstitutedExpression.split_sum() ]] solver.

      The following Python program runs in 63ms, and the internal run time of the generated program is 109µs.

      Run: [ @replit ]

      from enigma import SubstitutedExpression
      
      SubstitutedExpression.split_sum(
        ["ABCDEF"] * 4, "EFABCD",
        d2i={ 0: "ABCDEF" },
        distinct="",
        template="(4 * ABCDEF = EFABCD)",
      ).run()
      

      Like

    • GeoffR's avatar

      GeoffR 6:16 pm on 29 January 2023 Permalink | Reply

      from itertools import permutations
      
      for p1 in permutations('123456789', 6):
          A, B, C, D, E, F = p1
          ABCDEF = int(A + B + C + D + E + F) # old Tel. num.
          EFABCD = int(E + F + A + B + C + D) # new Tel. num.
          if 4 * ABCDEF == EFABCD:
              print(f"New Telephone Number = {EFABCD}")
      
      # New Telephone Number = 571428      
      
      
      

      Like

      • Jim Randell's avatar

        Jim Randell 11:11 pm on 29 January 2023 Permalink | Reply

        @GeoffR: I wasn’t sure that the puzzle text required the digits to be all different, so I allowed for repeats in my code. (Although it turns out they are all different).

        Like

    • GeoffR's avatar

      GeoffR 8:41 am on 30 January 2023 Permalink | Reply

      @JimR: I had assumed, with your repetend analogy, that the digits were probably meant to be different, although this it it not explicitly stated.

      My attached MiniZinc solution gives the same answer with the “all_different” constraint both in the code and remmed out, so it is not an explicit requirement.

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:A; var 1..9:B; var 1..9:C; var 1..9:D;
      var 1..9:E; var 1..9:F;
      
      %constraint all_different([A, B, C, D, E, F]);
      
      var 123456..987654: ABCDEF = 100000*A + 10000*B + 1000*C + 100*D + 10*E + F;
      var 123456..987654: EFABCD = 100000*E + 10000*F + 1000*A + 100*B + 10*C + D;
      
      % New number is precisely four times their old one.
      constraint EFABCD = 4 * ABCDEF;
      
      solve satisfy;
      output ["New telephone number = " ++ show(EFABCD) ];
      
      % New telephone number = 571428
      % ----------
      % ==========
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:02 pm on 27 January 2023 Permalink | Reply
    Tags:   

    Teaser 3149: Cube route 

    From The Sunday Times, 29th January 2023 [link] [link]

    I have a set of ten cards, each of which has a different digit written on it. All the cards have been used to make a set of prime numbers. After discarding the smallest prime, and without changing the order of any cards, I have placed the remaining primes in order of decreasing size to give a large number. It is possible, without changing the order of any cards, to break this number into a set composed entirely of cubes. Neither set contains a number with more than four digits.

    List, in order of decreasing size, my set of prime numbers.

    [teaser3149]

     
    • Jim Randell's avatar

      Jim Randell 4:31 pm on 27 January 2023 Permalink | Reply

      This Python program uses the [[ mcover() ]] (exact multiset cover) routine from the enigma.py library, that I implemented for Enigma 1712 (and also used in Teaser 2690).

      It runs in 228ms.

      Run: [ @replit ]

      from enigma import (
        primes, powers, inf, is_duplicate, group, item,
        multiset, mcover, trim, join, printf
      )
      
      # select numbers (as strings) with up to <k> digits and no repeated digits
      def select(seq, k=4):
        for n in seq:
          s = str(n)
          if len(s) > k: break
          if is_duplicate(s): continue
          yield s
      
      # cubes and primes up to 4-digits (as strings)
      cbs = group(select(powers(0, inf, 3)), by=item(0))  # grouped by first digit
      prs = dict((s, multiset.from_seq(s)) for s in select(primes))  # mapped to digit content
      
      # chop string <t> into segments from <ss>
      def chop(t, ss, rs=[]):
        # are we done?
        if not t:
          yield rs
        else:
          for s in ss.get(t[0], []):
            if t.startswith(s):
              yield from chop(trim(t, head=len(s)), ss, rs + [s])
      
      # find primes that cover each digit exactly once
      digits = multiset.from_seq("0123456789")
      for ps in mcover(prs, digits):
        # put them in order
        ps.sort(key=(lambda n: (len(n), n)), reverse=1)
        # make the large number, by discarding the smallest prime
        n = join(trim(ps, tail=1))
        # chop the large number into cubes
        for ss in chop(n, cbs):
          printf("{ps} -> {n} -> {ss}", ps=join(ps, sep=":"), ss=join(ss, sep=":"))
      

      Solution: The primes were: 827, 409, 61, 53.

      The initial set of primes found was (in decreasing order):

      (827, 409, 61, 53)

      The smallest of these (53) is discarded, and the rest assembled into the following sequence:

      82740961

      This can then be split into cubes as follows:

      (8, 27, 4096, 1)


      A variation on the puzzle (with a different answer) is achieved by placing the primes in ascending order, removing the smallest, and then splitting the remaining sequence into cubes.

      If the primes are arranged in increasing order we can start with:

      (53, 1409, 6827)

      Again, we discard the smallest prime (53), which leaves:

      14096827

      And this can be split into cubes as follows:

      (1, 4096, 8, 27)

      The same 4 cubes as the original puzzle, but in a different order.

      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