Recent Updates Page 63 Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 1:37 pm on 5 May 2019 Permalink | Reply
    Tags:   

    Teaser 2916: Pointless batting averages 

    From The Sunday Times, 12th August 2018 [link] [link]

    When my son was chosen to play cricket for his School First XI, I kept a record of the number of runs he scored in each of his first five innings. After each innings I calculated his batting average (the total number of runs scored so far divided by the number of innings) and found an interesting pattern:

    (i) Each score was under 30
    (ii) They [the scores] were all different
    (iii) Each of the five averages was a whole number

    When he asked me how he could maintain this pattern with his sixth innings, I was able to tell him the smallest score that would achieve this.

    What is the largest number this could have been?

    [teaser2916]

     
    • Jim Randell's avatar

      Jim Randell 1:37 pm on 5 May 2019 Permalink | Reply

      If the scores in the first five innings are (a, b, c, d, e) and there are scores for the sixth innings f, (between 0 and 29), that continue the pattern. And there will be a smallest such value:

      (a, b, c, d, e, f) → f_min

      So, we can look at all possible (a, b, c, d, e, f) values and find the largest possible f_min value.

      This Python program runs in 569ms.

      Run: [ @repl.it ]

      from enigma import (irange, Accumulator, printf)
      
      # possible next scores
      def scores(ss, avgs):
        t = sum(ss)
        n = len(ss) + 1
        for s in irange(-t % n, 29, step=n):
          if s not in ss:
            yield (ss + [s], avgs + [(t + s) // n])
      
      # find sequences of length k
      def solve(ss=[], avgs=[], k=5):
        if len(ss) == k:
          yield (ss, avgs)
        else:
          for (ss1, avgs1) in scores(ss, avgs):
            yield from solve(ss1, avgs1, k)
      
      # find the largest of the smallest values
      r = Accumulator(fn=max)
      
      for (ss, avgs) in solve():
        # find the smallest score to maintain this
        for (ss1, avgs1) in scores(ss, avgs):
          s = ss1[-1]
          r.accumulate(s)
          if s == r.value: printf("scores={ss} (avgs={avgs}) -> score={s} (avg={avg})", avg=avgs1[-1])
          break  # we only want the smallest value
      
      # output the solution
      printf("max value = {r.value}")
      

      Solution: The largest number it could have been is 23.

      I found 142 sequences that give this largest possible f_min value, although only 15 of these also have the averages take on 5 different values.

      One possible sequence is:

      (5, 11, 17, 27, 25)

      which give the corresponding averages of:

      (5, 8, 11, 15, 17)

      A score in the sixth innings of 23, would give an average of 18 over the six innings.

      Like

  • Unknown's avatar

    Jim Randell 2:13 pm on 4 May 2019 Permalink | Reply
    Tags: by: S G Worthington   

    Brain-Teaser 478: [Alphametic family] 

    From The Sunday Times, 26th July 1970 [link]

    Brian and Betty have a daughter, Moira, and this can be proved by addition where each letter is represented by a different digit:

    BRIAN + BETTY = MOIRA

    The sum of the individual digit values of MOIRA gives her age. The age of her brother ROBERT is similarly obtained. The sum of the children’s ages is a perfect square.

    How old is Robert?

    This puzzle was originally published with no title.

    [teaser478]

     
    • Jim Randell's avatar

      Jim Randell 2:14 pm on 4 May 2019 Permalink | Reply

      Once we have the solved the alphametic sum the value of ROBERT is determined.

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

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

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      "BRIAN + BETTY = MOIRA"
      
      "is_square(sum([M, O, I, R, A, R, O, B, E, R, T]))"
      
      --answer="sum([R, O, B, E, R, T])"
      

      But it is faster to write a short program that uses the [[ SubstitutedSum() ]] solver.

      This Python program runs in 79ms. (Internal runtime is 7.0ms).

      from enigma import (SubstitutedSum, is_square, printf)
      
      # make the alphametic sum
      p = SubstitutedSum(['BRIAN', 'BETTY'], 'MOIRA')
      
      # solve it
      for s in p.solve():
        # compute the ages
        (m, r) = (sum(s[x] for x in w) for w in ('MOIRA', 'ROBERT'))
        # check they sum to a square
        if not is_square(m + r): continue
        # output solution
        printf("r = {r} [m = {m}] [{s}]", s=p.substitute(s, "BRIAN + BETTY = MOIRA"))
      

      Solution: Robert is 23.

      Moira is 26. Together the ages sum to 49 (= 7²).

      There are 2 possible sums as the values of N and Y (in the units column of the sum) are interchangeable.

      So the sum is one of:

      14836 + 15007 = 29843
      14837 + 15006 = 29843

      Like

      • Jim Randell's avatar

        Jim Randell 2:40 pm on 22 November 2024 Permalink | Reply

        Or using the [[ SubstitutedExpression.split_sum ]] solver generates a program with an internal runtime of just 1.1ms.

        #! python3 -m enigma -rr
        
        SubstitutedExpression.split_sum
        
        "BRIAN + BETTY = MOIRA"
        
        --extra="is_square(sum([M, O, I, R, A, R, O, B, E, R, T]))"
        
        --answer="sum([R, O, B, E, R, T])"
        

        Like

    • GeoffR's avatar

      GeoffR 3:10 pm on 6 May 2019 Permalink | Reply

      % A solution in MinZinc 
      include "globals.mzn";
      
      var 0..9: B; var 0..9: R; var 0..9:I; var 0..9: A; var 0..9: N;
      var 0..9: E; var 0..9: T; var 0..9:Y; var 0..9: M; var 0..9: O;
      
      constraint B > 0 /\ M > 0 /\ R > 0;
      constraint all_different ([B, R, I, A, N, E, T, Y, M, O]);
      
      var 10000..99999: BRIAN = 10000*B + 1000*R + 100*I + 10*A + N;
      var 10000..99999: BETTY = 10000*B + 1000*E + 100*T + 10*T + Y;
      var 10000..99999: MOIRA = 10000*M + 1000*O + 100*I + 10*R + A;
      
      constraint BRIAN + BETTY == MOIRA;
      
      % The sum of the children’s ages is a perfect square
      set of int: sq = {9, 16, 25, 36, 49, 64, 81, 100};
      constraint  (M + O + I + R + A + R + O + B + E + R + T) in sq;
      
      solve satisfy;
      
      % The sum of the individual digit values gives each child's age
      output [ "ROBERT = " ++ show(R+O+B+E+R+T)] ++  
      [", MOIRA = " ++ show(M+O+I+R+A) ]
      ++ ["\nSum is " ++ show(BRIAN) ++ " + " ++ show(BETTY) ++ 
      " = " ++ show(MOIRA) ] ;
      
      % ROBERT = 23, MOIRA = 26
      % Sum is 14837 + 15006 = 29843
      % % time elapsed: 0.03 s
      % ----------
      % ROBERT = 23, MOIRA = 26
      % Sum is 14836 + 15007 = 29843
      % % time elapsed: 0.03 s
      % ----------
      % ==========
      % Finished in 254msec
      
      
      

      The parents ages (22 and 13) or (23 and 12) don’t seem to make much sense in relation to the children’s ages! ie Robert (23) and Moira(26)

      Like

  • Unknown's avatar

    Jim Randell 5:41 pm on 2 May 2019 Permalink | Reply
    Tags:   

    Teaser 2954: Lovely meter, RITA made! 

    From The Sunday Times, 5th May 2019 [link] [link]

    Revisiting the old curiosity shop, I bought an unusual moving-iron ammeter (made by Rho Iota Tau Associates). On the non-linear scale “9” was the last possible “whole amperes” scale graduation marked before the “full scale deflection” end stop (which was a half turn of the pointer from zero).

    The booklet gave the pointer swing from zero (in degrees) equal to the current (in amperes) raised to a fixed single-figure positive whole number power, then divided by a positive whole number constant. Curiously, the angle between “exact” pointer swings, calculated using this formula, for two single-figure “whole amperes” values was exactly a right angle.

    What, in amperes, were these two currents (lower first) and to what power were they raised?

    [teaser2954]

     
    • Jim Randell's avatar

      Jim Randell 5:44 pm on 2 May 2019 Permalink | Reply

      The title of the puzzle, of course, is a reference the song Lovely Rita by The Beatles.

      This Python program runs in 82ms.

      from enigma import (irange, subsets, div, fdiv, printf)
      
      # the deflection in degrees is d(x) = (x^n)/k
      
      # consider possible single figure powers n
      for n in irange(2, 9):
      
        # choose a and b the two single figure values
        for (a, b) in subsets(irange(0, 9), size=2):
      
          # determine the constant
          k = div(b**n - a**n, 90)
          if k is None: continue
      
          # 9 amps -> deflection =< 180 degrees
          # 10 amps -> deflection > 180 degrees
          if not (9**n <= 180 * k < 10**n): continue
          
          d = lambda x: fdiv(x**n, k)
          printf("n={n}, a={a} b={b}, k={k} [a->{da:.2f} b->{db:.2f} 9->{d9:.2f} 10->{d10:.2f}]", da=d(a), db=d(b), d9=d(9), d10=d(10))
      

      Solution: The two currents are 3 A and 9 A. They are raised to the power of 8.

      So the formula for the deflection (in degrees) as a function of the current (in amps) is:

      d(x) = (x^8) / 478224

      Giving the corresponding readings for currents from 0 to 10 amps:

       0 A →   0.000°
       1 A →   0.000°
       2 A →   0.001°
       3 A →   0.014° (d = 9/656)
       4 A →   0.137°
       5 A →   0.817°
       6 A →   3.512°
       7 A →  12.055°
       8 A →  35.082°
       9 A →  90.014° (d = 90 + 9/656)
      10 A → 209.107° (d > 180)

      So if you want to read small currents you had better be good at measuring very small angles.

      There are two further solutions for single digit powers and single digit currents that give a difference of exactly 90°.

      These are:

      d(x) = (x^4) / 72; for 3A and 9A
      d(x) = (x^6) / 2912; for 2A and 8A

      But these are disallowed by the condition that 9A should be on the scale and 10A off the scale. In the first case both 9A and 10A are on the scale, in the second case they are both off the scale. But they would be solutions to similar puzzles where the scale goes to 10A (but not 11A), or 8A (but not 9A), respectively.

      Like

  • Unknown's avatar

    Jim Randell 3:04 pm on 2 May 2019 Permalink | Reply
    Tags: by: G S Green   

    Brain-Teaser 477: [Tribute of goats] 

    From The Sunday Times, 19th July 1970 [link]

    His four wives have to make tribute of goats to the Khan of Bakristan. My job is to collect the goats.

    “Kahn Sahib says each gift to be divisible by donor’s age which consists of first and third digits of her number of goats”, said Munshi. “I don’t know ages, but know the goats required from each”.

    I knew their ages. To celebrate each wife’s 31st birthday the Khan had married a teenager, so I quickly jotted down the four numbers of goats — no names because Munshi was looking over my shoulder and reading each of my four numbers from right to left, as they do in Bakristan. “Numbers correct”, he said.

    Having done things the opposite way my numbers agreed with his.

    What are the ages of the 3rd and 4th wife?

    This puzzle was originally published with no title.

    [teaser477]

     
    • Jim Randell's avatar

      Jim Randell 3:05 pm on 2 May 2019 Permalink | Reply

      If we suppose the current ages of the four wives are:

      AB > CD > EF > GH

      Then the difference in the ages of consecutive wives is a number between 12 and 18.

      And the numbers of goats must be:

      APB, CQD, ERF, GSH

      (assuming each is a three digit number), where each number is divisible by the corresponding age.

      And this set of numbers can also be read as:

      BPA, DQC, FRE, HSG

      This is enough to allow us to use the general alphametic solver [[ SubstitutedExpression() ]] from the enigma.py library to find an answer.

      The following run file executes in 188ms.

      Run: [ @replit ]

      #! python -m enigma -rr
      
      SubstitutedExpression
      
      --distinct=""
      
      # ages in order
      "AB > CD > EF > GH > 12"
      
      # number of goats is divisible by the age
      "APB % AB = 0"
      "CQD % CD = 0"
      "ERF % EF = 0"
      "GSH % GH = 0"
      
      # age difference of consecutive wives
      "11 < AB - CD < 19"
      "11 < CD - EF < 19"
      "11 < EF - GH < 19"
      
      # the set of numbers is the same in reverse
      "ordered(APB, CQD, ERF, GSH) == ordered(BPA, DQC, FRE, HSG)"
      
      # answer is the current ages of the wives
      --answer="(AB, CD, EF, GH)"
      

      Solution: The third wife is 35. The fourth wife is 17.

      When the first wife is 31, the new (second) wife was 13.

      18 years later: The first wife is 49, the second wife is now 31, and the new (third) wife is 13.

      18 years later: The first wife is 67, the second wife is 49, the third wife is now 31, and the new (fourth) wife is 13.

      4 years later (brings us to now): The first wife is 71, the second wife is 53, the third wife is 35, and the fourth wife is 17.

      The corresponding numbers of goats are: 781, 583, 385, 187 (1936 goats in total).

      Like

  • Unknown's avatar

    Jim Randell 3:40 pm on 1 May 2019 Permalink | Reply
    Tags:   

    Teaser 2917: Polygoland 

    From The Sunday Times, 19th August 2018 [link] [link]

    We’ve all heard of Heligoland but George and Martha are on holiday in Polygoland. This is an island and when it was first inhabited, the authorities created as many national parks as possible subject to the restriction that each such park will be a regular polygon with the angle between each side being an integral number of degrees, and all the parks have different numbers of sides. Walking along the border between two such parks, Martha commented that the angle (A) of one of them was an exact multiple of the number of sides (S) in the other. George mentioned that the multiple was equal to the number of parks on the island.

    What are A and S?

    [teaser2917]

     
    • Jim Randell's avatar

      Jim Randell 3:40 pm on 1 May 2019 Permalink | Reply

      For a regular n-gon, the internal angles are (180 − 360 / n) degrees.

      So we can determine the number of possible n-gons with integer angles t from the number of divisors of 360 (greater than 2).

      There are 22 possible polygons, so t = 22

      So we need to find a solution to the equation:

      180 − 360 / n = 22m
      n = 360 / (180 − 22m)

      where n is a divisor of 360 (greater than 2).

      There are only a few values of m to consider and only one of them gives a viable value for n.

      Run: [ @repl.it ]

      from enigma import (divisors, irange, div, printf)
      
      # find divisors of 360 where n > 2
      ns = list(n for n in divisors(360) if n > 2)
      t = len(ns)
      printf("[{t} different polygons]")
      
      # now consider possible values of m
      for m in irange(1, 180 // t):
        n = div(360, 180 - t * m)
        if n is None or n == m or n not in ns: continue
        printf("A={A} degrees, S={m} [m={m} n={n}]", A=(180 - 360 // n))
      

      Solution: A = 176°, S = 8.

      The solution to the equation is m = 8, which gives a value of n = 90.

      The angle 176° is 4° off a straight line, so if we walk along the perimeter each side turns us by 4°. After 90 sides we have turned through 360°.

      176 = 22 × 8, and 8 is a divisor of 360, so there will be an octagonal park (with interior angles of 180° − 45° = 135°).

      Like

  • Unknown's avatar

    Jim Randell 8:10 am on 30 April 2019 Permalink | Reply
    Tags:   

    Brainteaser 1567: How many teams? 

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

    The teams in our local football league each play each of the others once in a season, earning three points for a win and one point for a draw. After the last Saturday of the season (when all the teams had played one game that day) I worked out the league table (with the teams in alphabetical order). I then consistently replaced digits in the table by letters, using different letters for different digits.

    Here is part of that table, showing some of the entries in three of the rows:

    What is the number of teams in the league? And what is the number TEAMS?

    This puzzle is included in the book Brainteasers (2002). The wording here is taken from the book and is only slightly changed from the original puzzle.

    [teaser1567]

     
    • Jim Randell's avatar

      Jim Randell 8:11 am on 30 April 2019 Permalink | Reply

      If there are n teams in the league, then at the end of the season each team has played all the other (n − 1) teams, and this total number of matches must be represented in the sum of the “won”, “drawn”, “lost” columns in the table.

      H + O + W = n − 1
      M + A + N = n − 1
      T + E + A = n − 1

      If each team played one match on the final Saturday, then there must be an even number of teams. And if n is even, then (n − 1) is odd.

      We are given the points in the third row:

      3T + E = S

      And we are given the “goals against” for two teams. Each “lost” game involves conceding at least one goal, so:

      NY, AM

      (and the values cannot be equal).

      Together these give us enough information to assign values to the letters.

      We can solve these alphametic expressions using the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      The following run file executes in 216ms.

      Run: [ @repl.it ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      # sums of "won", "drawn", "lost" are the same
      "H + O + W == M + A + N == T + E + A"
      
      # sum is odd
      "(H + O + W) % 2 = 1"
      
      # points for third row
      "3 * T + E = S"
      
      # "lost" <= "goals against"
      "N < Y"
      "A < M"
      
      # answer: (number of teams, value of TEAMS)
      --answer="(H + O + W + 1, TEAMS)"
      

      Solution: There are 12 teams in the league. TEAMS = 16459.

      The first row has “won”, “drawn”, “lost” values of 0, 3, 8, but we don’t know which order.

      The second row has 5 “won”, 4 “drawn”, 2 “lost”, and 7 “goals against”.

      The third row has 1 “won”, 6 “drawn”, 4 “lost” and 5 “goals against”, giving 9 points.

      There are 12 teams, so there are 66 matches played in total.

      Like

  • Unknown's avatar

    Jim Randell 10:47 am on 29 April 2019 Permalink | Reply
    Tags:   

    Teaser 2918: Prime multiplication 

    From The Sunday Times, 26th August 2018 [link] [link]

    Almost everyone knows that the single digit prime numbers are 2, 3, 5, and 7, the number 1 having been excluded quite a long time ago.

    Here is a multiplication involving prime digits:

    What is the answer?

    [teaser2918]

     
    • Jim Randell's avatar

      Jim Randell 10:47 am on 29 April 2019 Permalink | Reply

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

      The following run file executes in 113ms.

      Run: [ @replit ]

      #! python -m enigma -rr
      
      #        A B C
      #    *     D E
      #    ---------
      #      F G H J
      #    K L M N
      #    ---------
      #    P Q R S T
      #    =========
      
      SubstitutedExpression
      
      # use only prime digits
      --digits="2,3,5,7"
      --distinct=""
      
      "ABC * DE = PQRST"
      "ABC * E = FGHJ"
      "ABC * D = KLMN"
      
      # required answer
      --answer="PQRST"
      

      Solution: The result of the multiplication is 25575.

      If the digit 1 were allowed, there would be a further 9 solutions (including one that does not have the digit 1 in the result).

      Like

    • GeoffR's avatar

      GeoffR 1:58 pm on 29 April 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
      
      set of int: S = {2,3,5,7};    % single digit primes
      
      var S: a;  var S: b;  var S: c;  var S: d;
      var S: e;  var S: f;  var S: g;  var S: h;
      var S: i;  var S: j;  var S: k;  var S: m;
      var S: n;  var S: p;  var S: q;  var S: r;
      var S: s;  var S: t;  
      
      %      a b c
      %   x    d e
      %    -------
      %    f g h i
      %  j k m n 0
      %  ---------
      %  p q r s t
      %  ---------
      
      var 100..999: abc = 100*a + 10*b + c;
      var 10..99: de = 10*d + e;
      var 10000..99999: pqrst = 10000*p + 1000*q + 100*r + 10*s + t;
      var 1000..9999: fghi = 1000*f + 100*g + 10*h + i;
      var 10000..99999: jkmn0 = 10000*j + 1000*k + 100*m + 10*n;
      
      constraint abc * de == pqrst;
      constraint abc * d * 10 == jkmn0;
      constraint abc * e == fghi;
      
      solve satisfy;
      
      % a = 7; b = 7; c = 5; d = 3; e = 3;
      % f = 2; g = 3; h = 2; i = 5; 
      % j = 2; k = 3; m = 2; n = 5; 
      % p = 2; q = 5; r = 5; s = 7; t = 5;
      % time elapsed: 0.02 s
      %----------
      %==========
      % Sum is:
      %     775
      %   x  33
      %   ----
      %    2325
      %   23250
      %   -----
      %   25575
      %   -----
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:50 am on 28 April 2019 Permalink | Reply
    Tags:   

    Teaser 2919: Letters puzzle 

    From The Sunday Times, 2nd September 2018 [link] [link]

    My best friend has a special birthday later this month, and I have composed a Teaser to celebrate the occasion.

    First of all, I wrote that date as a single number (with the day at the start, the month in the middle and the year at the end).

    Then, replacing different letters consistently with different non-zero digits, I found that the sum of LETTERS and PUZZLE gives that number.

    Find the prime value of TEASER.

    [teaser2919]

     
    • Jim Randell's avatar

      Jim Randell 8:51 am on 28 April 2019 Permalink | Reply

      The sum is of the form:

      LETTERS + PUZZLE = abc92018

      Where a, b, c allow the result to read as a valid date in September 2018 (after the date of the puzzle, which is 2nd September 2018).

      If the date is read as: ab.09.2018, we have: 3 ≤ ab ≤ 30; c = 0.

      If the date is read as: bc.9.2018, we have: a = 0; 3 ≤ bc ≤ 30.

      Note that if the result of the sum is 3092018, the birthday could be on 03.09.2018 or 30.9.2018.

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

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression.split_sum
      
      # upper case letters are distinct
      --distinct="AELPRSTUZ"
      
      # but non-zero
      --invalid="0,AELPRSTUZ"
      
      # digits stand for themselves
      --literal="01289"
      
      # expressions to solve
      "{LETTERS} + {PUZZLE} = {abc92018}"
      --extra="is_prime({TEASER})"
      
      # the result of the sum should read as a valid September date
      --code="valid = lambda d, f, v=0: f == v and 2 < d < 31"
      --extra="valid({ab}, {c}) or valid({bc}, {a})"
      
      # required answer
      --answer="{TEASER}"
      
      # [optional] faster prime checking
      --code="is_prime = is_prime_mr"
      

      Solution: TEASER = 314719.

      The sum is: 2133197 + 658821 = 2792018.

      And so the date is 27.9.2018 (27th September 2018).

      Like

    • Frits's avatar

      Frits 12:11 pm on 13 August 2025 Permalink | Reply

      Two calls to is_prime().

      from functools import reduce
      from enigma import is_prime
      
      # LETTERS + PUZZLE = ab92018  (as L must be even) ab < 31 or b = 0
       
      # convert digits to a number
      d2n = lambda *s: reduce(lambda x, y: 10 * x + y, s)
      
      nums = set(range(1, 10))
      
      # e < 6 as u = 6 - e 
      for e in range(1, 6):
        s = 8 - e 
        for r in nums - {e, s}:
          # TEASER is a prime number
          if r not in {1, 3, 7, 9}: continue
          # (R + L) % 10 = 1
          if not (0 < (l := 11 - r) < 10): continue
          # (E + Z + 1) % 10 = 0
          if not (0 < (z := 9 - e) < 10): continue
          # (T + Z + 1) % 10 = 2,  T = 11 - Z = 2 + E
          t = e + 2
          if not (0 < (t := 11 - z) < 10): continue
          # (T + U + 1) % 10 = 9, U = 8 - T, U = 6 - E
          u = 6 - e
          # different digits
          if len(unused := nums - {e, s, r, l, z, t, u}) != 2: continue
         
          letters = d2n(l, e, t, t, e, r, s)
          # L must be even, if L >= 3: P + E = 10, if L = 2: P + E <= 10
          for p in [u for u in unused if (u + e < 11 if l == 2 else u + e == 10)]:
            puzzle = d2n(p, u, z, z, l, e)
            for a in unused - {p}:
              if is_prime(teaser := d2n(t, e, a, s, e, r)):
                print("answer:", teaser)
      

      Like

  • Unknown's avatar

    Jim Randell 8:17 am on 27 April 2019 Permalink | Reply
    Tags: by: G F Anderson   

    Brain-Teaser 476: [Football pools] 

    From The Sunday Times, 12th July 1970 [link]

    A football pools fan suggests a novel points scoring system which, he says, is a lot of fun and so easy to do.

    For Home wins and Draws the goals for teach match are written down (Home teams first, of course), and the figures placed next to each other. This gives the points. For example, a Home team winning by 10 goals to 3 scores 103 points, a 5-5 Draw 55 points, and so on. You have to select a given number of matches, for example, eight, from the list, which the object of making the highest points score.

    I need not tell you about points for Away wins, because I did not include any among my selections when I tried out the system the other day. All my forecasts were correct. They comprised 2 Home Wins, and the remainder were all Draws. One of my Home wins was worth 2 more points than the other Home win. No match had a goals aggregate greater than 16, and the points obtained from my 2 Home wins accounted for exactly 60 per cent of the points obtained from all the matches I selected.

    How many points did I score?

    This puzzle was originally published with no title.

    [teaser476]

     
    • Jim Randell's avatar

      Jim Randell 8:18 am on 27 April 2019 Permalink | Reply

      This Python 3 program runs in 93ms.

      Run: [ @repl.it ]

      from enigma import (nsplit, nconcat, irange, subsets, div, join, printf)
      
      # points for a match with a score of <x>-<y>
      def points(x, y):
        return nconcat(nsplit(x) + nsplit(y))
      
      # possible wins
      wins = list()
      for x in irange(1, 16):
        wins.extend((x, y, points(x, y)) for y in irange(0, min(x - 1, 16 - x)))
      
      # possible draws
      draws = list((x, x, points(x, x)) for x in irange(0, 8))
      
      # find k draws that give t points
      def solve(k, t, ds=draws, s=[]):
        if k == 0:
          if t == 0:
            yield s
        else:
          for (i, (x, y, p)) in enumerate(ds):
            if not (p > t):
              yield from solve(k - 1, t - p, ds[i:], s + [(x, y)])
      
      # choose the two home wins (different)
      for ((x1, y1, p1), (x2, y2, p2)) in subsets(wins, size=2):
        if not (abs(p1 - p2) == 2): continue
      
        # p1 + p2 accounts for exactly 60% of the points
        # so, calculate the total number of points
        w = p1 + p2
        t = div(100 * w, 60)
        if t is None: continue
      
        # find 5 draws (not necessarily all different) worth the remaining 40%
        for (i, ds) in enumerate(solve(5, t - w)):
          if i == 0: printf("total {t} pts; wins = {x1}-{y1}; {x2}-{y2}")
          printf("  draws = {ds}", ds=join((join(d, sep="-") for d in ds), sep="; "))
          break # only need one example
      

      Solution: Your selection scored 440 points.

      Possible draws are 0-0, 1-1, …, 8-8, scoring 0, 11, …, 88 points respectively. So draws always score some multiple of 11 points.

      There are 16 ways to have two wins that have scores differing by 2, but only one of these gives the remaining 40% of points being a multiple of 11.

      That is: wins of 13-1 and 13-3, which have scores of 131 points and 133 points respectively.

      Together these give 264 points, which is 60% of a total of 440 points, leaving 176 points to be made up from the draws, and 176 = 16 × 11.

      There are 63 ways in which we can choose 5 draws to give a total of 176 points. For example: two 8-8 matches, and three 0-0 matches.

      Like

  • Unknown's avatar

    Jim Randell 8:01 am on 26 April 2019 Permalink | Reply
    Tags:   

    Teaser 2953: Marble tower 

    From The Sunday Times, 28th April 2019 [link] [link]

    Liam has a number of bags of marbles; each bag contains the same number (more than 1) of equal-size marbles.

    He is building a tetrahedron with the marbles, starting with a layer which fits snugly in a snooker triangle. Each subsequent triangular layer has one fewer marble along each edge. With just one bag left he had completed a whole number of layers; the number of marbles along the edge of the triangle in the last completed layer was equal to the number of completed layers. The last bag had enough marbles to just complete the next layer.

    How many bags of marbles did Liam have?

    [teaser2953]

     
    • Jim Randell's avatar

      Jim Randell 8:24 am on 26 April 2019 Permalink | Reply

      This Python program runs in 85ms.

      from enigma import (irange, inf, T, div, printf)
      
      # P(n) = the nth tetrahedral number
      P = lambda n: (n * (n + 1) * (n + 2)) // 6
      
      def solve():
        # suppose there are n bags, each containing k marbles
        # there are enough marbles in the final bag to complete a layer
        # so the number of marbles in a bag is a triangular number
        for x in irange(2, inf):
          k = T(x)
      
          # and there must be (x + 1) completed layers
          # and layers T(x + 1) ... T(2x + 1) have used (n - 1) k marbles
          # so: P(2x + 1) - P(x) = (n - 1) k
          # solve for (n - 1)
          n = div(P(2 * x + 1) - P(x), k)
          if n:
            yield (k, n + 1, x)
      
      for (k, n, x) in solve():
        printf("{n} bags, each containing {k} marbles, layers 1 - {x} (of {t}) remaining", t=2 * x + 1)
        break
      

      Solution: There were 20 bags of marbles.


      We can simplify the equation:

      P(2x + 1) − P(x) = (n − 1)T(x)

      to:

      n = 7x/3 + 17/3 + 2/x

      For integer x the first two terms give us a whole number of thirds, so the 2/x term must also provide a whole number of thirds, i.e. x = 1, 2, 3, or 6.

      And the only values to give an integer value for n are:

      x = 1, n = 10
      x = 6, n = 20

      There are T(x) marbles in each of the n bags, and this is more than 1, so this eliminates the first solution leaving, T(6) = 21 marbles in each of the 20 bags.

      Here’s a Python program that uses the analysis:

      from enigma import (div, printf)
      
      for x in [2, 3, 6]:
        n = div((7 * x + 17) * x + 6, 3 * x)
        if n:
          printf("n={n} [x={x}]")
      

      Like

  • Unknown's avatar

    Jim Randell 8:16 am on 25 April 2019 Permalink | Reply
    Tags:   

    Brainteaser 1563: Family sum 

    From The Sunday Times, 23rd August 1992 [link]

    In this puzzle digits have been consistently replaced by letters, with different letters being used for different digits. This addition sum then makes sense:

    also AND is divisible by three.

    What is the number REAGAN?

    This puzzle is included in the book Brainteasers (2002). The wording is only slightly changed from the original puzzle.

    [teaser1563]

     
    • Jim Randell's avatar

      Jim Randell 8:17 am on 25 April 2019 Permalink | Reply

      This puzzle can easily be solved using the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      The following run-file executes in 480ms.

      Run: [ @replit ]

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      "RONALD + AND + NANCY = REAGAN"
      
      "AND % 3 = 0"
      
      --answer="REAGAN"
      

      Solution: REAGAN = 396168.

      The symbols L and C appear in the tens column, but not elsewhere, so their values can be interchanged. This gives rise to the two possible sums:

      308627 + 687 + 86854 = 396168
      308657 + 687 + 86824 = 396168

      Like

      • Jim Randell's avatar

        Jim Randell 8:41 am on 9 June 2023 Permalink | Reply

        For a faster solution we can use the [[ SubstitutedExpression.split_sum ]] solver.

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

        Run: [ @replit ]

        #! python3 -m enigma -rr
        
        SubstitutedExpression.split_sum
        
        "RONALD + AND + NANCY = REAGAN"
        
        --extra="AND % 3 = 0"
        
        --answer="REAGAN"
        

        Like

    • GeoffR's avatar

      GeoffR 12:20 pm on 25 April 2019 Permalink | Reply

      % A Solution in MiniZinc
      include "globals.mzn";
       
      var 0..9: R; var 0..9: O; var 0..9: N; var 0..9: A;  var 0..9: L; 
      var 0..9: D; var 0..9: C; var 0..9: Y; var 0..9: E;  var 0..9: G; 
      
      constraint R != 0 /\ A != 0 /\ N != 0;
      constraint all_different( [R,O,N,A,L,D,C,Y,E,G]);
      
      var 100..999: AND = 100*A + 10*N + D;
      var 10000..99999: NANCY = 10000*N + 1000*A + 100*N + 10*C + Y;
      
      var 100000..999999: RONALD = 100000*R + 10000*O + 1000*N 
      + 100*A + 10*L + D;
      
      var 100000..999999: REAGAN = 100000*R + 10000*E + 1000*A 
      + 100*G + 10*A + N;
      
      constraint AND mod 3 == 0;
      
      constraint RONALD + AND + NANCY == REAGAN;
      
      solve satisfy;
      
      output [show(RONALD) ++ " + " ++ show(AND) ++ " + " ++ 
      show(NANCY) ++ " = " ++ show(REAGAN)];
      
      % 308657 + 687 + 86824 = 396168
      % time elapsed: 0.02 s
      % ----------
      % 308627 + 687 + 86854 = 396168
      % time elapsed: 0.02 s
      %----------
      %==========
      
      

      Like

    • Frits's avatar

      Frits 1:44 pm on 9 June 2023 Permalink | Reply

        
      column 3: x + N + A = .A with x = 1,2,3 so N = 8,9,0
      
      column 2: y + O + N = E so either:
      
      N = 9, is not possible
      N = 8 and O = 0 and x = 2  
      N = 0 causes y to be zero but then O = E
      
      --> N = 8, O = 0, E = 9 and x = 2
      
      column 4:
      z + A + A + N = 2G so z + A + A >= 21 - 8 so A = 6,7
      
      using AND is divisible by three:
      (A, D, Y) is either (6, 7, 4) or (7, 3, 2)
      (A, D, Y, L+C) is either (6, 7, 4, 7) or (7, 3, 2, 9)
      (A, D, Y, {L, C}) is either (6, 7, 4, {2, 5}) or (7, 3, 2, {4, 5})
      
      (A, G) = (6, 1) as A = 7 causes G to be 3 (which is same as D)
      
      so (N, O, E, A, D, Y, G) = (8, 0, 9, 6, 7, 4, 1) with {L, C} = {2, 5}
      This leaves R = 3
      

      Like

  • Unknown's avatar

    Jim Randell 10:47 am on 24 April 2019 Permalink | Reply
    Tags:   

    Teaser 2920: Barcode 

    From The Sunday Times, 9th September 2018 [link] [link]

    When Fred opened his “10 to 99 Store” (the numbers reflecting the prices of the goods in pounds) there was trouble from the start when the barcode reader scanned the prices backwards. First at the self-service checkout was Mrs Adams, who kept quiet when she was charged £59.49 for a £94.95 item. The next two customers, Mr Baker and Mr Coles, paid by card, without noticing they had in fact been overcharged. All three had bought a differently-priced item, and by coincidence, in the case of the two men, the price each had been charged was a whole multiple of the actual price.

    How much had the shop lost or gained overall on the three transactions?

    [teaser2920]

     
    • Jim Randell's avatar

      Jim Randell 10:48 am on 24 April 2019 Permalink | Reply

      This Python program runs in 157ms.

      (The following is for Python 2.7, see the code on repl.it for the Python 3 version).

      Run: [ @repl.it ]

      from enigma import (Accumulator, irange, nreverse, div, printf)
      
      # r accumulates the total gain for the shop
      def transaction(t, (p, q)):
        d = q - p
        printf("[{n}: price = {p} -> charged = {q}, diff = {d}]", n=r.count)
        return t + d
      
      r = Accumulator(fn=transaction, value=0)
      
      # transaction A
      p = 9495
      q = nreverse(p)
      assert q < p
      r.accumulate((p, q))
      
      # for transactions B and C, consider 4-digit prices
      for p in irange(1000, 9999):
        # reverse the price
        q = nreverse(p)
        if not (q > p): continue
        # reversed price is an exact multiple
        m = div(q, p)
        if m is None or m < 2: continue
        r.accumulate((p, q))
      
      # there should be three transactions in total
      assert r.count == 3
      
      # output total
      printf("total shop gain = {g:.2f} pounds", g=r.value * 0.01)
      

      Solution: In total the shop gained £ 117.00 over the three transactions.

      The transactions for B and C are:

      (1) paying £ 98.01 for an item priced at £ 10.89 (9 times)
      (2) paying £ 87.12 for an item priced at £ 21.78 (4 times)

      Like

  • Unknown's avatar

    Jim Randell 10:48 am on 23 April 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 475: Club lockers 

    From The Sunday Times, 5th July 1970 [link]

    The lockers in one section of the new club-house are numbered 1 to 12 consecutively. Last Saturday, Pitcher arrived without his key. He was surprised to find that his locker could be opened by the key to Putter’s locker which is next to his.

    Pitcher at once saw Wedge, the secretary, and Bunker, the captain. From them he learned that there are only 3 different key patterns for the 12 lockers (patterns A, B and C) and that the total of the numbers on the 4 A lockers is the same as the corresponding total for the 4 B lockers, which is the same as that for the 4 C lockers.

    Wedge also told Pitcher that no two lockers with pattern A keys are adjoining. He added that his own key is of the same pattern as Wood’s and that the total of the numbers on Wood’s and Wedge’s lockers is 16. He further mentioned that of the 3 lockers, other than the captain’s own locker, which can be opened by the captain’s key, the nearest to the captain’s locker is further from the captain’s locker than are 5 (but not more) lockers which cannot be opened by the captain’s key.

    By this time, Pitcher was making for the wall but if the number on Putter’s locker is higher than the number on Wedge’s locker — what is the number on Bunker’s locker?

    This puzzle is included in the book Sunday Times Brain Teasers (1974).

    [teaser475]

     
    • Jim Randell's avatar

      Jim Randell 10:49 am on 23 April 2019 Permalink | Reply

      This Python 3 program runs in 84ms.

      Run: [ @repl.it ]

      from enigma import (irange, subsets, tuples, diff, printf)
      
      # possible locker numbers
      lockers = irange(1, 12)
      
      # find subsets of size 4 that sum to 26 (= sum(lockers) / 3)
      s4s = list(s for s in subsets(lockers, size=4) if sum(s) == 26)
      
      # choose pairs from the given sets
      def pairs(*ss):
        for s in ss:
          yield from subsets(s, size=2)
      
      # choose a set of lockers for key pattern A
      for A in s4s:
        # there are no consecutive numbers in A
        if any(y - x == 1 for (x, y) in tuples(A, 2)): continue
      
        # choose a (disjoint) set that includes Bunker's key
        for X in s4s:
          if set(A).intersection(X): continue
      
          # and the remaining set
          Y = diff(lockers, A + X)
      
          # choose a locker for Bunker
          for b in X:
      
            # find the distance of the nearest other locker to b in X
            d = min(abs(b - x) for x in X if x != b)
      
            # there must be exactly 5 lockers not in X closer to b
            n = sum(abs(b - x) < d for x in lockers if x not in X)
            if not (n == 5): continue
      
            # Wedge's and Wood's lockers (in the same set) sum to 16
            for (w1, w2) in pairs(A, X, Y):
              if not (w1 + w2 == 16): continue
      
              # Pitcher's and Putter's lockers (in the same set) are adjacent
              for (p1, p2) in pairs(A, X, Y):
                if not (p2 - p1 == 1): continue
      
                # all people are different
                if not (len(set((b, w1, w2, p1, p2))) == 5): continue
      
                # Putter's locker has a higher number than Wedge's
                if not (max(p1, p2) > min(w1, w2)): continue
      
                printf("A={A} X={X} Y={Y}, b={b} d={d}, ws=({w1}, {w2}) ps=({p1}, {p2})")
      

      Solution: Bunker has locker number 2.

      The A pattern keys are for lockers (1, 3, 10, 12). The other pattern keys are lockers (2, 7, 8, 9) and (4, 5, 6, 11).

      Wedge and Wood have lockers 5 and 11 (respectively).

      Pitcher and Putter have lockers 7, 8 or 8, 9 (in some order).

      Like

  • Unknown's avatar

    Jim Randell 9:21 am on 22 April 2019 Permalink | Reply
    Tags:   

    Teaser 2921: Octavia the octagonarian 

    From The Sunday Times, 16th September 2018 [link] [link]

    Queen Octavia’s emblem was two concentric regular octagons (the outermost’s side length equal to the innermost’s distance between opposite sides). Seen from above her eightieth-birthday, level, cheesecake torte, with octagonal cavity all the way through and vertical side-faces, matched the emblem. Its outer side-faces were square and a two-figure whole number of inches wide. A four-feet diameter cylindrical cover protected it. At the party the whole torte was used, without wastage, to levelly fill a number of identical cuboid dishes (internally having length, width and depth, in inches, each a different single-figure whole number greater than one). Curiously, the number of dishes was a three-figure value with different numerals in descending order.

    What was the torte’s volume in cubic inches?

    [teaser2921]

     
    • Jim Randell's avatar

      Jim Randell 9:22 am on 22 April 2019 Permalink | Reply

      This Python program runs in 78ms.

      from enigma import (irange, subsets, nsplit, tuples, sqrt, divf, div, printf)
      
      # diameter of a regular octagon with side 1 unit
      d = sqrt(4 + 2 * sqrt(2))
      
      # possible volumes of the dishes
      vs = set(a * b * c for (a, b, c) in subsets(irange(2, 9), size=3))
      
      # is <n> a k-digit descending number?
      def check(n, k=3):
        ds = nsplit(n)
        return (len(ds) == k and all(a > b for (a, b) in tuples(ds, 2)))
      
      # consider <x>, the side length of the outer octagon = the distance
      # between opposite faces of the inner octagon
      # the outer octagon can fit in a 48 inch tube
      for x in irange(10, min(99, divf(48, d))):
      
        # volume of cake
        V = 4 * x**3
      
        # consider the volume of each dish
        for v in vs:
      
          # the number of dishes is:
          n = div(V, v)
          if n is None or not check(n): continue
      
          printf("x={x} V={V}, v={v} n={n}")
      

      Solution: The volume of the torte was 23,328 cubic inches.

      The outside faces of the cake are 18 inch squares, and this is the largest cake that will fit inside a 48 inch diameter tube.

      There are 2 possibilities for the size of the serving dishes, either 972 dishes measuring 2×3×4 inches, or 432 dishes measuring 2×3×9 inches.

      Although the larger dish size has a number of dishes composed of consecutive descending digits (which is possibly what the setter had in mind), I think the smaller sized dish makes the most sense. Which means there were almost 1,000 guests catered for.

      Like

  • Unknown's avatar

    Jim Randell 12:51 pm on 21 April 2019 Permalink | Reply
    Tags:   

    Brainteaser 1557: An alphabetical jigsaw 

    From The Sunday Times, 12th July 1992 [link]

    I have some jigsaw pieces which fit together to form a 5-by-5 square with the letters all the right way up. Here is an attempt to make the jigsaw:

    The attempt has failed because the last piece does not fit the right way up. In fact it is possible to make the 5-by-5 jigsaw so that the 25 different letters spell six words in reading order.

    What is this arrangement?

    This puzzle appears in the book Brainteasers (2002). The wording above is taken from the book, but is only slightly changed from the original puzzle.

    [teaser1557]

     
    • Jim Randell's avatar

      Jim Randell 12:52 pm on 21 April 2019 Permalink | Reply

      There are two parts to the program. The first is concerned with fitting the pieces into the grid. The second part is then reading the letters in the grid as a collection of words.

      This Python program runs in 6.6s, but most of the time is taken up with collecting the word list. I used a collection of allowable Scrabble words, which gives 49,595 viable words.

      Run: [ @replit ] (using just the selected words)

      from itertools import product
      from collections import (Counter, defaultdict)
      from enigma import (irange, find, chunk, flatten, join, printf)
      
      (X, Y) = (1, 7)
      
      pieces = [
        { 0: 'H', Y: 'Z', X + Y: 'F', X + Y + Y: 'X' },
        { 0: 'P', X: 'S', X + X: 'C' },
        { 0: 'I', Y: 'J', Y + Y: 'O' },
        { 0: 'G', X: 'Y', X + Y: 'M' },
        { 0: 'T', Y: 'V', Y + Y: 'N' },
        { 0: 'E', Y: 'K', X + Y: 'W' },
        { 0: 'U', Y: 'R', X + Y: 'D' },
        { 0: 'A', X: 'L', X + Y: 'B' },
      ]
      
      # create the empty grid
      grid = [None] * (Y * Y)
      for (x, y) in product(irange(1, 5), irange(1, 5)):
        grid[x + y * Y] = '.'
      
      # fit piece p into grid g at index i
      # return new grid or None
      def fit(g, p, i):
        g = g.copy()
        for (k, v) in p.items():
          x = g[i + k]
          # non-usable square?
          if x != '.': return None
          g[i + k] = v
        return g
      
      def solve(ps=pieces, g=grid):
        # are we done?
        if not ps:
          # return the completed (unpadded) grid
          yield list(r[1:-1] for (i, r) in enumerate(chunk(g, Y), start=1) if 1 < i < Y)
        else:
          # find an empty square
          i = find(g, '.')
          if i != -1:
            for (j, p) in enumerate(ps):
              g2 = fit(g, p, i)
              if g2 is not None:
                yield from solve(ps[:j] + ps[j + 1:], g2)
      
      # list of words to examine
      file = "words.txt"
      
      # collect letters from the pieces
      letters = Counter()
      for p in pieces: letters.update(p.values())
      
      # collect words that can be formed from the letters
      words = defaultdict(list)
      for w in open(file).readlines():
        w = w.strip().upper()
        if not (Counter(w) - letters):
          words[w[0]].append(w)
      
      printf("[collected {n} words from {file}]", n=sum(len(v) for v in words.values()))
      
      # form text t into a sequence of words
      def check(t, s=[]):
        if not t:
          yield s
        else:
          for w in words[t[0]]:
            if t.startswith(w):
              yield from check(t[len(w):], s + [w])
      
      
      # fit the pieces into the grid
      for g in solve():
        # attempt to form the letters into words
        wss = list(check(join(flatten(g))))
        if wss:
          # output the grid
          for r in g:
            printf("{r}", r=join(r, sep=" "))
          # output the words
          for ws in wss:
            if len(ws) == 6:
              printf("words: {ws}", ws=join(ws, sep=", "))
          printf()
      

      Solution: The completed jigsaw looks like this:

      So the 6 words are: GYP, SCHMALTZ, FIB, VEX, JUNK, WORD.

      There are 64 ways to fit the pieces into the grid, but only one of them makes a set of viable words.

      There are 2 fifteen letter words in the list that can be made from the collection of letters in the puzzle: DERMATOGLYPHICS, UNCOPYRIGHTABLE.

      Like

  • Unknown's avatar

    Jim Randell 9:04 am on 20 April 2019 Permalink | Reply
    Tags: by: E C Parker   

    Brain-Teaser 474: [Triangular park] 

    From The Sunday Times, 28th June 1970 [link]

    Three friends live at the side entrances to a park bordered by three straight roads. Alan’s entrance is on the shortest road, Colin’s on the longest East to West road, and Brian’s on the road of mid length.

    Brian and Colin are directly North and South apart across the park, for half the distance they each are by road from Alan. The distance Brian and Colin are apart, plus the length of the three roads, is three miles.

    Each entrance is a number of exact yards by road, from any corner of the park, and Alan is as near to one corner as possible.

    How far from that corner is he?

    This puzzle was originally published with no title.

    [teaser474]

     
    • Jim Randell's avatar

      Jim Randell 9:06 am on 20 April 2019 Permalink | Reply

      If B and C’s gates are at a distance of d apart N-S across the park, and distances b and c from a corner X, then (b, c, d) form a Pythagorean triple.

      Once we have a suitable Pythagorean triple we can extend the lines XB and XC by lengths of 2d and bend them (at integer values) so that the bent sides form the third side of the triangle, which meet at A’s gate.

      If this is possible we have a viable solution. We then need to find which solution places A’s gate closest to a corner of the park.

      This Python program finds candidates solutions and choose the one with the smallest distance from A’s gate to a corner. It runs in 108ms.

      from enigma import (pythagorean_triples, irange, div, Accumulator, printf)
      
      # find the minimum distance of A from a corner
      r = Accumulator(fn=min)
      
      # BCX is right angled triangle with integer sides
      for (x, y, z) in pythagorean_triples(5280):
        for (b, c, d) in [(z, x, y), (z, y, x)]:
      
          # check 5d + b + c = 5280 yards
          if not (5 * d + b + c == 5280): continue
      
          # now consider possible integer values for y
          for y in irange(1, 2 * d - 1):
      
            # compute viable z (using the cosine rule)
            p = (b - c) * (b * b + b * (4 * d + c) + 4 * d * (c + 2 * d - y))
            q = 2 * (b * b + b * (2 * d + y) + c * (y - c - 2 * d))
            z = div(p, q)
            if z is None or not (0 < z < 2 * d): continue
      
            # compute the sides of the park
            (A, B, C) = (y + z, b + 2 * d - z, c + 2 * d - y)
      
            # A is on the shortest side and C is on the longest side
            if not (A < B < C): continue
      
            # additional: the park is a right angled triangle
            #if not (A * A + B * B == C * C): continue
      
            printf("[A={A} B={B} C={C}, d={d} b={b} c={c}, y={y} z={z}]")
      
            r.accumulate_data(min(y, z), (A, B, C, d, b, c, y, z))
      
      # output the solution
      printf("min distance for A from a corner = {r.value} yards [{r.count} solutions]")
      

      Solution: The shortest distance A’s gate can be from a corner is 135 yards.

      The program finds 8 possible solutions:

      A=1218 B=1400 C=2002, d=660 b=1100 c=880, y=198 z=1020
      A=1155 B=1540 C=1925, d=660 b=1100 c=880, y=275 z=880
      A=1122 B=1650 C=1848, d=660 b=1100 c=880, y=352 z=770
      A=1110 B=1750 C=1760, d=660 b=1100 c=880, y=440 z=670
      A=780 B=1800 C=2220, d=480 b=1480 c=1400, y=140 z=640
      A=750 B=1850 C=2200, d=480 b=1480 c=1400, y=160 z=590
      A=678 B=2050 C=2072, d=480 b=1480 c=1400, y=288 z=390
      A=429 B=2196 C=2325, d=330 b=1830 c=1800, y=135 z=294

      The last of these has the smallest value for y or z.

      So the park looks like this:


      However, apparently this was not the intended answer to this puzzle. The puzzle text should have said that the park was a right angled triangle, but this extra condition was omitted when the puzzle was published.

      We can remove solution candidates that are not right-angled triangles by uncommenting the check at line 29.

      If we do this we find that only one of the solutions remains:

      A=1155 B=1540 C=1925, d=660 b=1100 c=880, y=275 z=880

      The shortest distance being 275 yards.

      In this case the park looks like this:

      However, given there is only a single solution it seems odd to have the statement: “Alan is as near to one corner as possible”. It would make more sense to just ask: “How far is Alan from the nearest corner?”.

      Like

  • Unknown's avatar

    Jim Randell 8:29 pm on 19 April 2019 Permalink | Reply
    Tags:   

    Teaser 2922: Inscribed 

    From The Sunday Times, 23rd September 2018 [link]

    The Republic of Mathematica has an unusual rectangular flag. It measures 120 cm by 60 cm and has a red background. It features a green triangle and a white circle. All the lengths of the sides of the triangle and the radius of the circle (which touches all three sides of the triangle) are whole numbers of cm. Also, the distances from the vertices of the triangle to the centre of the circle are whole numbers of cm. The flag has a line of symmetry.

    What is the length of the shortest side of the triangle?

    [teaser2922]

     
    • Jim Randell's avatar

      Jim Randell 8:29 pm on 19 April 2019 Permalink | Reply

      The flag has a line of symmetry, so I supposed the triangle was isosceles, with sides a, a, b.

      If we split it in half down the middle we get a right-angled triangle, with base q = b/2, height h and hypotenuse a.

      The height h can be split into r the radius of the incircle (an integer) plus x the distance from the incentre to a vertex of the triangle (also an integer), so is itself an integer.

      (b/2)² = a² − h²

      The right hand side is the difference of two integers, so is an integer, and hence b/2 is an integer.

      So (q, h, a) is a Pythagorean triple.

      The inradius r can be calculated as the area of the isosceles triangle, divided by its semiperimeter.

      r = qh / (a + q)

      And this must be an integer.

      We can the calculate the distance y from the incentre to the lower vertices:

      y = hypot(q, r)

      And this also must be an integer, so (r, q, y) is also a Pythagorean triple.

      This Python program runs in 69ms.

      Run: [ @replit ]

      from enigma import (pythagorean_triples, div, is_square, arg, printf)
      
      # check a (q, h, a) pythagorean triangle (q = b/2)
      def check(q, h, a):
        # inradius = area / semiperimeter
        r = div(q * h, a + q)
        if r is None: return
        y = is_square(r * r + q * q)
        if y is None: return
        printf("a={a} b={b}, r={r}, x={x} y={y}", b=2 * q, x=h - r)
      
      # maximum length line in a 60 x 120 square is intf(hypot(60, 120)) = 134
      M = arg(134, 0, int)
      
      # consider pythagorean triples with hypotenuse up to M
      for (a, b, h) in pythagorean_triples(M):
        check(a, b, h)
        check(b, a, h)
      

      Solution: The shortest side of the triangle is 56 cm.

      The isosceles triangle has sides measuring 100 cm, 100 cm, 56 cm.

      The radius of the incircle is 21 cm. The upper vertex of the triangle is 75 cm from the incentre, the lower vertices are 35 cm from the incentre.

      Like

  • Unknown's avatar

    Jim Randell 8:31 am on 18 April 2019 Permalink | Reply
    Tags:   

    Brainteaser 1547: Doing the rounds 

    From The Sunday Times, 3rd May 1992 [link]

    This week, I share a find-the-next-row puzzle that is doing the rounds of dons’ whiteboards:

    1
    1 1
    2 1
    1 2 1 1
    ?

    To avoid invasion of ivory towers, I will give you the answer:

    1 1 1 2 2 1

    with the explanation that, starting with the initial 1, each subsequent row is obtained by reading the previous row. Thus, row five is formed (with reference to row four) from one “one”, followed by one “two”, and terminating with two “one”s.

    However, I do have four questions about the first billion rows of this sequence.

    1. What is the largest digit that can be found anywhere?
    2. What is the largest number of ones that can occur consecutively in any single row?
    3. Repeat (2), looking for twos instead.
    4. Repeat (2), looking for threes instead.

    Multiply each answer by its question number and send in the total.

    This puzzle is included in the book Brainteasers (2002), in which it appears in the following form:

    Read me!

    Consider the sequence:

    1
    11
    21
    1211
    111221
    312211

    You might like to try and work out the next few terms before reading on and trying the rest of this Teaser.

    In fact, having started with 1, each subsequent term simply reads the previous line. So, for example, after 111221 we note that this consists of:

    three ones, two twos, one one

    i.e. the next term is simply:

    312211

    Here are some questions about the first billion terms of this sequence:

    (a) What is the largest number of consecutive ones in any term?
    (b) What is the largest number of consecutive twos in any term?
    (c) What is the largest number of consecutive threes in any term?
    (d) What is the largest digit which can be found in any term?

    [teaser1547]

     
    • Jim Randell's avatar

      Jim Randell 8:33 am on 18 April 2019 Permalink | Reply

      This Python program generates the first few terms of the sequence. To do the first 12 terms takes 80ms.

      Run: [ @replit ]

      from enigma import (repeat, chunk, arg, printf)
      
      # transform the input sequence s, by counting the runs of digits
      def transform(s):
        r = list()
        while s:
          x = s[0]
          for (j, y) in enumerate(s):
            if j > 0 and y != x:
              r.extend([j, x])
              s = s[j:]
              break
          else:
            r.extend([j + 1, x])
            break
        return r
      
      # how many sequences to examine
      N = arg(12, 0, int)
      
      # record max runs (in the previous term)
      m = dict()
      
      # repeatedly apply the transform, starting with [1]
      for (i, s) in enumerate(repeat(transform, [1]), start=1):
        if N < 15: printf("({i}) -> {s}")
      
        # each transformed sequence consists of (n, d) pairs
        # telling us there were n runs of digit d in the previous term
        if i > 1:
          for (n, d) in chunk(s, 2):
            if n > m.get(d, 0):
              m[d] = n
      
        if not (i < N): break
      
      # output solutions
      for k in sorted(m.keys()):
        printf("digit {k} -> {n} times", n=m[k])
      printf("max digit = {k}")
      

      Together with some analysis we can now answer the questions:

      First we note that we can’t split runs of the same digit, so if we have (for example) five d‘s, …ddddd…., they will appear in the next sequence as …(5d)…, and not as …(2d)(3d)… etc.

      So in any transformed sequence we cannot have two pairs appearing consecutively for the same digit, i.e. …(xd)(yd)… would not appear, because it would be …({x+y}d)…

      So, we certainly cannot have a sequence of four consecutive digits …(dd)(dd)… appearing in a transformed sequence.

      But neither can we have …(xd)(dd)(dy)… appearing, as that also has two pairs appearing consecutively for the same digit.

      So we cannot have a run of more than three consecutive digits in any transformed sequence.

      Which means in any transformed sequence we will not see a digit greater than 3.

      Running the program we see that in the first 12 sequences we have three 1’s appearing in sequence 5:

      (5) → [1, 1, 1, 2, 2, 1]

      and three 2’s appearing in sequence 7:

      (7) → [1, 3, 1, 1, 2, 2, 2, 1]

      but we only manage two 3’s in sequence 11:

      (11) → [1, 1, 1, 3, 1, 2, 2, 1, 1, 3, 3, 1, 1, 2, 1, 3, 2, 1, 1, 3, 2, 1, 2, 2, 2, 1]

      And in fact we can see that it is not possible to achieve three 3’s.

      If we think about the first sequence in which …333… appears, then the digits must be paired as …(33)(3x)… (as …(x3)(33)… is not possible), but then the (33) indicates that the sequence before this one must have had a run of three 3’s (followed by three of another digit). But this is a contradiction. So we cannot find a first sequence with three 3’s.

      So that answer to puzzle from the book is:

      Solution: (a) 3; (b) 3; (c) 2; (d) 3.

      And solution for the original puzzle is: 1×3 + 2×3 + 3×3 + 4×2 = 26.

      To consider the first 40 sequences take my program 5.5s, and the 40th sequence has 63,138 digits, so it is not suitable for attempting to examine the first billion terms.

      The sequence is known as the “look and say” sequence [@wikipedia].

      Like

  • Unknown's avatar

    Jim Randell 12:55 pm on 17 April 2019 Permalink | Reply
    Tags:   

    Teaser 2923: Powerful numbers 

    From The Sunday Times, 30th September 2018 [link] [link]

    George and Martha’s five daughters have been investigating large powers of numbers. Each daughter told the parents that they had worked out a number which was equal to its last digit raised to an exact power. When Andrea announced her power, the parents had a 50% chance of guessing the last digit. When Bertha announced a larger power, the same applied. When Caroline announced her power, the parents had only a 25% chance of guessing the last digit; with Dorothy’s larger power, the same applied. When Elizabeth announced hers, the parents only had a 12.5% chance of guessing the last digit. I can tell you that the five powers were consecutive two-digit numbers adding up to a perfect square.

    What, in alphabetical order of the daughters, were the five powers?

    [teaser2923]

     
    • Jim Randell's avatar

      Jim Randell 12:55 pm on 17 April 2019 Permalink | Reply

      We ignore the digits 0 and 1 (as 0^k = 0 and 1^k = 1 for positive k), which leaves the digits 2 to 9.

      A chance of 50% is 1 out of 2, 25% is 1 out of 4, and 12.5% is 1 out of 8, so we are looking for a collection of consecutive numbers where 2 numbers have a choice from 2, another 2 have a choice from 4, and the remaining number has a choice from 8.

      This Python program looks at sequences of 5 consecutive 2-digit numbers, and when it finds one that sums to a square it checks that the choices for the digits conform to this pattern.

      It runs in 71ms.

      Run: [ @repl.it ]

      from enigma import (irange, tuples, is_square, icount, printf)
      
      # consider 5-sequences of consecutive 2-digit numbers for the powers
      for ks in tuples(irange(10, 99), 5):
        # the 5 powers sum to a square
        if is_square(sum(ks)) is None: continue
      
        # find the number of digits (ignoring 0 and 1) where d^k mod 10 = d
        ns = list(icount(irange(2, 9), (lambda d: pow(d, k, 10) == d)) for k in ks)
        if sorted(ns) != [2, 2, 4, 4, 8]: continue
      
        # extract indices for the given value
        indices = lambda v: (i for (i, n) in enumerate(ns) if n == v)
      
        # A has the first 2, B has the second 2
        (A, B) = indices(2)
        # C has the first 4, D has the second 4
        (C, D) = indices(4)
        # E has the 8
        (E,) = indices(8)
        
        printf("A={A} B={B} C={C} D={D} E={E}", A=ks[A], B=ks[B], C=ks[C], D=ks[D], E=ks[E])
      

      Solution: The five powers are: A=44, B=46, C=43, D=47, E=45.

      There are only three sequences that sum to a square:

      (18, 19, 20, 21, 22) → 10²
      (43, 44, 45, 46, 47) → 15²
      (78, 79, 80, 81, 82) → 20²

      And only one of these gives the right set of choices when raising the digits 2-9 to the corresponding powers.


      Analytically:

      If we consider digits d from 2 to 9, and look at increasing powers k such that d^k end in the digit d we get:

      k=1: d=2, 3, 4, 5, 6, 7, 8, 9
      k=2: d=5, 6
      k=3: d=4, 5, 6, 9
      k=4: d=5, 6
      k=5: d=2, 3, 4, 5, 6, 7, 8, 9
      k=6: d=5, 6
      k=7: d=4, 5, 6, 9
      k=8: d=5, 6
      k=9: d=2, 3, 4, 5, 6, 7, 8, 9
      k=10: d=5, 6

      We see that there is a repeating pattern, by count of the number of digits, of: (8, 2, 4, 2)…

      So for powers of: 1, 5, 9, 13, 17, … there is a choice of 8 possible digits (a 12.5% chance).

      For powers of: 2, 4, 6, 8, 10, 12, … there is a choice of 2 possible digits (a 50% chance).

      For powers of: 3, 7, 11, 15, … there is a choice of 4 possible digits (a 25% chance).

      The five girls have chosen 5 consecutive powers with two 50% chances (2), two 25% chances (4) and one 12.5% chance (8), so the part of the sequence they have chosen is … (4, 2, 8, 2, 4).

      We know the 8’s occur when k = 4n + 1.

      So the powers the girls have chosen are:

      (4n − 1, 4n, 4n + 1, 4n + 2, 4n + 3)

      These are 2-digit numbers, which limits n to the range [3, 24].

      The sum of the powers is:

      20n + 5

      and this needs to be a square number.

      >>> list(n for n in irange(3, 24) if is_square(20 * n + 5))
      [11]
      

      So, n = 11, and the girls numbers (and digits counts) are:

      43 (4), 44 (2), 45 (8), 46 (2), 47 (4)

      A and B both have counts of 2, C and D both have counts of 4, E has a count of 8.

      Like

  • Unknown's avatar

    Jim Randell 8:57 am on 16 April 2019 Permalink | Reply
    Tags:   

    Teaser 2952: Silly slip 

    From The Sunday Times, 21st April 2019 [link] [link]

    Please help me find my silly slip. I correctly added a five-figure number to a four-figure number to give a six-figure total. Then I tried to substitute letters for digits systematically and I ended up with:

    SILLY + SLIP = PLEASE

    However, in these letters I have made one silly slip, so please find it and then work out what the correct sum was.

    What was the correct six-figure numerical answer?

    This puzzle appears in the books The Sunday Times Brain Teasers 1 (2019) and The Sunday Times Teasers Book 1 (2021).

    [teaser2952]

     
    • Jim Randell's avatar

      Jim Randell 8:58 am on 16 April 2019 Permalink | Reply

      We can use the [[ bungled_sum() ]] solver (originally written for Puzzle 56).

      Run: [ @replit ]

      >>> bungled_sum(['SILLY', 'SLIP', 'PLEASE'])
                      L
      SILLY + SLIP = P?EASE / @[2,1] L -> ?
      97225 + 9271 = 106496 / ?=0 A=4 E=6 I=7 L=2 P=1 S=9 Y=5
      

      Solution: The numerical result of the sum is 106496.

      The mistake is in the L of PLEASE (the result of the sum), it should be a letter that is different from all the other letters, although that does make it hard to make an acceptable word, but we can check this makes a viable alphametic sum using the [[ SubstitutedSum() ]] solver from the enigma.py library.

      % python enigma.py SubstitutedSum "SILLY + SLIP = PXEASE"
      (SILLY + SLIP = PXEASE)
      (97225 + 9271 = 106496) / A=4 E=6 I=7 L=2 P=1 S=9 X=0 Y=5
      

      Like

      • Jim Randell's avatar

        Jim Randell 4:06 pm on 20 April 2019 Permalink | Reply

        I assumed this puzzle was in the same vein as other “bungled sum” problems.

        But the text says that letters are substituted for digits “systematically”, but it doesn’t say that each letter stands for a different digit (which is usual in alphametic puzzles).

        If we allow letters to stand for the same digit, then we can solve the alphametic sum:

        % python enigma.py SubstitutedExpression "SILLY + SLIP = PLEASE" --distinct=""
        (SILLY + SLIP = PLEASE)
        (99007 + 9091 = 108098) / A=0 E=8 I=9 L=0 P=1 S=9 Y=7
        [1 solution]
        

        The duplicated digits are: A and L are both 0, I and S are both 9.

        Like

      • Jim Randell's avatar

        Jim Randell 11:01 pm on 21 April 2019 Permalink | Reply

        Here is a faster (but longer) solution, using the minizinc.py library.

        from minizinc import (MiniZinc, var, alphametic, substitute)
        
        # the sum is a 5-digit number plus a 4-digit number and a 6-digit result
        #
        #    a b c d e      S I L L Y
        #      f g h i        S L I P
        #  -----------    -----------
        #  j k m n p q    P L E A S E
        
        fmt = "{abcde} + {fghi} = {jkmnpq}"
        
        # create the model
        p = MiniZinc(f"""
        
        include "globals.mzn";
        
        % the symbols in the incorrect sum
        {var("0..9", "AEILPSY")};
        
        constraint all_different([A, E, I, L, P, S, Y]);
        
        % symbols for the correct sum
        {var("0..9", "abcdefghijkmnpq")};
        
        % the correct sum
        constraint {alphametic(fmt)};
        
        % no leading zeros
        constraint a != 0 /\ f != 0 /\ j != 0;
        
        % the incorrect sum differs in only one place
        constraint sum([
          a != S, b != I, c != L, d != L, e != Y,
          f != S, g != L, h != I, i != P,
          j != P, k != L, m != E, n != A, p != S, q != E,
        ]) = 1;
        
        solve satisfy;
        
        """)
        
        # solve it
        for s in p.solve():
          # output the sum
          print(substitute(fmt, s))
        

        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