Recent Updates Page 57 Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

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

    Teaser 2819: An age-old problem 

    From The Sunday Times, 2nd October 2016 [link] [link]

    Five men of different ages under fifty are celebrating their joint birthday in the pub. Alan’s age is the average of their five ages. When Bob is three times Alan’s age today, the sum of Alan’s and Colin’s ages will equal the sum of their five ages today. Furthermore, Derek will then be three times his age today, and Eric will be one year more than double Bob’s age today.

    The landlord checked that the youngest of the five was allowed to buy alcohol.

    Who is the youngest, and how old is he?

    [teaser2819]

     
    • Jim Randell's avatar

      Jim Randell 10:50 am on 23 October 2019 Permalink | Reply

      The conditions in the puzzle text give us 4 equations in 5 variables:

      4A − B − C − D − E = 0
      6A − 3B − D − E = 0
      3A − B − 2D = 0
      3A − 3B + E = 1

      If we set a value for one of the ages, then the other 4 ages are determined.

      We can then look for a set of integer ages, where only the youngest member of the party is asked for proof of age.

      I supposed the barman might ask anyone who looked 21 or younger for proof of age, and this gives a unique solution.

      This Python program uses the [[ matrix.linear() ]] solver from the enigma.py library to solve the equations. It runs in 148ms.

      Run: [ @repl.it ]

      from enigma import irange, matrix, as_int, arg, printf
      
      # the constraints give the following four equations:
      #
      #   4A -  B -  C -  D - E = 0
      #   6A - 3B      -  D - E = 0
      #   3A -  B      - 2D     = 0
      #   3A - 3B           + E = 1
      
      eqs = [
        # A   B   C   D   E
        [ 4, -1, -1, -1, -1 ], # = 0
        [ 6, -3,  0, -1, -1 ], # = 0
        [ 3, -1,  0, -2,  0 ], # = 0
        [ 3, -3,  0,  0,  1 ], # = 1
        [ 1,  0,  0,  0,  0 ], # = A
      ]
      
      # age range for the men (min, max)
      m = arg( 1, 0, int)
      M = arg(49, 1, int)
      printf("[ages: min = {m}, max = {M}]")
      
      # choose a value for A
      for a in irange(m, M):
      
        # solve the equations for integers
        try:
          ss = tuple(as_int(x) for x in matrix.linear(eqs, [0, 0, 0, 1, a]))
        except ValueError:
          continue
      
        # discard any solutions with ages not in the required range
        if any(x < m or x > M for x in ss): continue
      
        # count how many are 21 or under?
        n = sum(x < 22 for x in ss)
        if n != 1: continue
      
        # output the solution
        s = min(zip(ss, "ABCDE"))
        (A, B, C, D, E) = ss
        printf("youngest={s[1]} age={s[0]} [A={A} B={B} C={C} D={D} E={E}]")
      

      Solution: Colin is the youngest. He is 20.

      There are three sets of ages (between 1 and 49) that satisfy the equations:

      A=6 B=8 C=4 D=5 E=7 (min=4)
      A=17 B=23 C=12 D=14 E=19 (min=12)
      A=28 B=38 C=20 D=23 E=31 (min=20)

      In the first two sets more than one of the “men” is below the legal age to buy alcohol (18 in the UK), so the third set is the most likely answer. The youngest man is aged 20, and so could reasonably be asked for proof of age.

      If we were to restrict the minimum age to 18 only the final set is possible. (And this remains true if we take the minimum age down as far as 13).

      Like

    • GeoffR's avatar

      GeoffR 3:04 pm on 23 October 2019 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      % Alan, Bob, Colin, Derek, Eric
      var 1..49: A; var 1..49: B; var 1..49: C;
      var 1..49: D; var 1..49: E; 
      
      % Jim's four equations
      constraint 4*A - B - C - D - E == 0;
      constraint 6*A - 3*B - D - E == 0;
      constraint 3*A - B - 2*D == 0;
      constraint 3*A - 3*B + E  == 1;
      
      % Minimum age to buy alcohol = 18
      constraint min([A,B,C,D,E]) > 17;
      
      solve satisfy;
      
      output ["Alan = " ++ show(A) ++ ", Bob = " ++ show(B) ++ ", Colin = " ++ show(C) ++ 
      ", Derek = " ++ show(D) ++ ", Eric = " ++ show(E)] ++ 
      ["\nYoungest of five people = " ++ show(min([A,B,C,D,E])) ++ " years"]
      
      % Alan = 28, Bob = 38, Colin = 20, Derek = 23, Eric = 31
      % Youngest of five people = 20 years
      % ----------
      % ==========
      % Finished in 151msec
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:19 pm on 18 October 2019 Permalink | Reply
    Tags:   

    Teaser 2978: Norfolk Flats 

    From The Sunday Times, 20th October 2019 [link] [link]

    Sam has purchased Norfolk Flats; an area of farmland (less than 100 hectares) bordered by six straight fences. He intends to farm an area which is an equilateral triangle with corners that are the midpoints of three of the existing boundaries. This creates three more distinct areas (one for each of his sons); these areas are identical in shape and size and have two sides that are parallel.

    Sam measured the area (in square metres) which each son will farm and also his own area. One of the numbers is a square and the other a cube. If I told you which was which, you should be able to work out the area of Norfolk Flats.

    What (in square metres) is that area?

    [teaser2978]

     
    • Jim Randell's avatar

      Jim Randell 5:34 pm on 18 October 2019 Permalink | Reply

      I supposed that the plot of land in question was a regular hexagon.

      Then, if the hexagon has side x the area of Sam’s triangular enclosure is:

      sam = (9/16)x²√3

      and the area of the enclosure for each son is:

      son = (5/16)x²√3

      So we can say Sam’s enclosure is 9 area units and each son’s enclosure is 5 area units.

      Here is a visual representation of the situation:

      So, we need to look for squares and cubes where 5 times one of them is 9 times the other.

      This Python program runs in 83ms.

      Run: [ @replit ]

      from enigma import (irange, inf, div, is_square, printf)
      
      # max area (100 hectares = 1_000_000 square metres)
      M = 1000000
      
      # collect the areas for each case (sam, son, total)
      (case1, case2) = (list(), list())
      
      # consider values for the cube
      for x in irange(1, inf):
        cube = x ** 3
        if not (8 * cube < 3 * M): break
      
        # does 5 * square = 9 * cube ?
        square = div(9 * cube, 5)
        if square is not None and is_square(square):
          (sam, son) = (square, cube)
          area = sam + 3 * son
          if area < M:
            printf("[1] son = cube = {cube} -> sam = square = {square}, area = {area}")
            case1.append((sam, son, area))
      
        # does 9 * square = 5 * cube ?
        square = div(5 * cube, 9)
        if square is not None and is_square(square):
          (sam, son) = (cube, square)
          area = sam + 3 * son
          if area < M:
            printf("[2] sam = cube = {cube} -> son = square = {square}, area = {area}")
            case2.append((sam, son, area))
      
      # consider the cases
      for ss in (case1, case2):
        if len(ss) != 1: continue
        (sam, son, area) = ss[0]
        printf("area = {area} [sam = {sam}, son = {son}]")
      

      Solution: The total area of Norfolk Flats is 243,000 square metres (= 24.3 hectares).

      Sam’s enclosure is 91,125 square metres (= 45³).

      Each son’s enclosure is 50,625 square metres (= 225²).

      So each side of the hexagon is about 305.83 metres long.

      This is the only viable solution where the area of Sam’s enclosure is a perfect cube, and the area of each son’s enclosure is a perfect square. So it is the answer to the puzzle.

      If the area of Sam’s enclosure is a perfect square, and the area of each son’s enclosure is a perfect cube, we find there are three potential solutions (where the total area is below 1 million square metres):

      sam = 225 = 15²; son = 125 = 5³; area = 600
      sam = 14400 = 120²; son = 8000 = 20³; area = 38400
      sam = 164025 = 405²; son = 91125 = 45³; area = 437400

      So this case is ruled out as the answer.


      Manually:

      [1] In the case: 5a² = 9b³

      We see that 3 must divide a, and 5 must divide b. So:

      let: a = 3p, b = 5q
      → p² = 25q³

      So 5 must divide p:

      let: p = 5r
      → r² = q³

      So we are looking for numbers that are simultaneously squares and cubes, i.e. powers of 6.

      r² = q³ = k⁶
      r = k³, q = k²
      → a = 15k³, b = 5k²

      And we are interested in cases where:

      a² +3b³ < 1,000,000
      600 k⁶ < 1,000,000
      → k = 1, 2, 3

      So there are three possible solutions in this case (those given above).

      [2] In the case: 5a³ = 9b²

      We can similarly arrive at a solution of:

      a = 45k², b = 225k³

      And we require:

      a³ + 3b² < 1,000,000
      243,000 k⁶ < 1,000,000
      → k = 1

      So in this case there is a single solution, and from this we get the answer to the puzzle.

      Like

    • Robert Brown's avatar

      Robert Brown 10:39 pm on 18 October 2019 Permalink | Reply

      It doesn’t say the fences are the same length. Alternate short & long fences makes a diagram that fits the words in the text – only restriction I can see is that ‘son’ is < 'sam'. If this is true, I don't see a possible solution.

      Like

      • Jim Randell's avatar

        Jim Randell 11:03 pm on 18 October 2019 Permalink | Reply

        @Robert: I think if you don’t require the hexagon to be regular it is possible to find side lengths that will work for many different (square, cube) combinations, so it wouldn’t be possible to work out the total area being told which of the enclosures areas was a square which was a cube.

        But with a regular hexagon there are many fewer possibilities and we can find a unique solution, so it is probably what the setter had in mind (although not what the text of the puzzle explicitly states).

        Like

    • GeoffR's avatar

      GeoffR 3:30 pm on 22 October 2019 Permalink | Reply

      
      # This solution uses Jim's diagram i.e son/sam = 5/9 in area ratio
      # F + 3.(5/9).F < 1000000 -> F < 375000
      # Hence squares < 613, cubes < 73
      
      from collections import defaultdict
      
      # Two dictionaries to collect squares and cubes for each case
      # i.e 5 * square = 9 * cube or 9 * square = 5 * cube
      
      d1 = defaultdict(list)  # 5 * square = 9 * cube
      d2 = defaultdict(list)  # 9 * square = 5 * cube
      
      # F + 3.(5/9).F < 1000000 -> F < 375000
      # hence squares < 613, cubes < 73
      
      sq = [n * n for n in range(10, 613)]
      cb = [n * n * n for n in range(10, 73)]
      
      for x in sq:
        for y in cb:
          if 5 * x == 9 * y:    
            d1[x] += [(x, y)]  
          # Other solution     
          if 9 * x == 5 * y:
            d2[x] += [(x, y)] 
      
      # One of the two dictionaries must have a single solution
      for k,v in d1.items():
        if len(v) == 1 and len(d1) == 1:
          print(f"Norfolk Flats Area = {3 * v[0][0] + v[0][1]} sm")
          print(f"Son's area = {v[0][0]} sm, Sam's area = {v[0][1]} sm")
          
      for k,v in d2.items():
        if len(v) == 1 and len(d2) == 1:
          print(f"Norfolk Flats Area = {3 * v[0][0] + v[0][1]} sm")
          print(f"Son's area = {v[0][0]} sm, Sam's area = {v[0][1]} sm")
      
      

      Like

  • Unknown's avatar

    Jim Randell 9:57 am on 18 October 2019 Permalink | Reply
    Tags:   

    Teaser 2821: Magic cards 

    From The Sunday Times, 16th October 2016 [link] [link]

     Joe placed nine cards on the table to form the magic square shown on the left below (where each row, column and diagonal has the same total). Then he turned over each card one at a time and the result is shown on the right below: it is not magic.

    Penny then rearranged the cards to form a magic square which, after each card was turned over, was also magic.

    What (in increasing order) were the four corner numbers in her magic square with the higher total?

    [teaser2821]

     
    • Jim Randell's avatar

      Jim Randell 9:58 am on 18 October 2019 Permalink | Reply

      A magic square can be characterised using three variables: x, y, z as the sums:

      
      a = x+y       | b = x+z+z | c = x+y+y+z
      --------------+-----------+------------
      d = x+y+y+z+z | e = x+y+z | f = x
      --------------+-----------+------------
      g = x+z       | h = x+y+y | i = x+y+z+z
      
      

      Each row, column, and diagonal combine to give 3(x+y+z) = the magic constant.

      Given values for a, e, f we can derive: x = f, y = a − f, z = e − a and generate the complete square.

      This Python program solves the puzzle in 87ms.

      Run: [ @replit ]

      from enigma import (unpack, div, subsets, cproduct, printf)
      
      # make an additive magic square (a b c d e f g h i) given (a e f)
      def magic(a, e, f):
        (x, y, z) = (f, a - f, e - a)
        return (
          x + y, x + z + z, x + y + y + z,
          x + y + y + z + z, x + y + z, x,
          x + z, x + y + y, x + y + z + z,
        )
      
      # is a magic square canonical? (a < c, g, i; b < d)
      is_canonical = unpack(lambda a, b, c, d, e, f, g, h, i: a < min(c, g, i) and b < d)
      
      # the cards are all different, so can stand for themselves
      # (here we list them in canonical sorted order)
      cards = [ (1, 12), (2, 7), (3, 9), (3, 13), (4, 7), (4, 11), (5, 14), (6, 8), (8, 9) ]
      
      # consider a card both ways up
      flips = unpack(lambda x, y: ((x, y), (y, x)))
      
      # we arrange the cards as:
      #
      #   a1 b1 c1    a2 b2 c2
      #   d1 e1 f1    d2 e2 f2
      #   g1 h1 i1    g2 h2 i2
      
      # the centre card must have a sum of s
      s = div(sum(x + y for (x, y) in cards), 9)
      assert s is not None
      
      # find a card with the right sum for the e's
      for (k, (e2, e1)) in enumerate(cards):
        if not (e1 + e2 == s): continue
      
        # choose cards for the a's and the f's
        for (a, f) in subsets(cards[:k] + cards[k + 1:], size=2, select="P"):
          for ((a1, a2), (f1, f2)) in cproduct([flips(a), flips(f)]):
            # and generate the squares
            s1 = magic(a1, e1, f1)
            if not is_canonical(s1): continue
            s2 = magic(a2, e2, f2)
            # check the corresponding cards
            cs = sorted(min(flips(c)) for c in zip(s1, s2))
            if cs != cards: continue
            # collect the corners (a, c, g, i)
            corners = sorted(s1[x] for x in (0, 2, 6, 8))
            printf("corners={corners} [s1={s1} s2={s2}]")
      

      Solution: The four corner squares are: 3, 7, 9, 13.

      The magic constant in the first square is 24, in the second square it is 18.

      Like

  • Unknown's avatar

    Jim Randell 9:38 am on 17 October 2019 Permalink | Reply
    Tags:   

    Brainteaser 1734: Scratchcard 

    From The Sunday Times, 10th December 1995 [link]

    Every Saturday The Daily Broadsheet gives readers a free scratchcard comprising two crosses and a number of ticks concealed beneath silver foil squares. Readers have to scratch just three of the squares to reveal what is beneath. Anyone who scratches only ticks can use the card to obtain a 50p discount on The Sunday Broadsheet. The probability of revealing three ticks, expressed as a percentage, is a whole number larger than 50%.

    To increase circulation the paper intends to increase the number of silver squares, still with only two crosses. This will increase the chances of finding ticks when scratching three squares, and again the probability will be a whole number percentage.

    How many more silver squares do they intend to add?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1734]

     
    • Jim Randell's avatar

      Jim Randell 9:39 am on 17 October 2019 Permalink | Reply

      If there are n ticks (where n ≥ 3), then the probability of scratching off 3 ticks is:

      (n / (n + 2)) × ((n − 1) / (n + 1)) × ((n − 2) / n)
      = (n − 1)(n − 2) / (n + 1)(n + 2)

      This Python program finds values of n where this probability is an integer percentage, greater than 50%.

      Run: [ @repl.it ]

      from enigma import irange, inf, first, printf
      
      # find n, p where probability p is an integer percentage > m
      def solve(m):
        for n in irange(3, inf):
          (p, r) = divmod(100 * (n - 1) * (n - 2), (n + 1) * (n + 2))
          if r == 0 and p > m: yield (n, p)
          if p == 99 and r > 0: break
      
      # find the first two (n, p) values with p > 50
      ((n1, p1), (n2, p2)) = first(solve(50), 2)
      d = n2 - n1
      printf("{d} more squares [{n1} ticks -> {p1}%; {n2} ticks -> {p2}%]")
      

      Solution: They intend to add 9 more squares.

      With 16 squares (14 ticks and 2 crosses) the probability is 65%.

      With 25 squares (23 ticks and 2 crosses) the probability is 77%.

      In fact there are only 4 values for n which give an integer percentage for p:

      n = 3, p = 10%
      n = 4, p = 20%
      n = 14, p = 65%
      n = 23, p = 77%

      Like

  • Unknown's avatar

    Jim Randell 9:41 am on 16 October 2019 Permalink | Reply
    Tags: ,   

    Teaser 2825: Twin sets 

    From The Sunday Times, 13th November 2016 [link] [link]

    The twins Wunce and Repete each made a list of positive perfect squares. In Wunce’s list each of the digits 0 to 9 was used exactly once, whereas in Repete’s list each of the digits was used at least once.

    Wunce commented that the sum of his squares equalled their year of birth, and Repete responded by saying that the sum of his squares was less than the square of their age.

    What is the sum of Wunce’s squares, and what is the sum of Repete’s?

    As stated there are multiple potential solutions to the puzzle. In the comments I give some additional conditions that allow a unique solution to be found (which is the same as the published solution).

    [teaser2825]

     
    • Jim Randell's avatar

      Jim Randell 9:42 am on 16 October 2019 Permalink | Reply

      As originally stated there are multiple solutions to this puzzle.

      I made the following additional suppositions in order to allow a unique solution to be arrived at.

      1. the puzzle is set on/after the twins birthday in 2018;
      2. the lists do not contain repeats;
      3. the squares are greater than 1.

      The following Python program then finds the unique solution in 281ms.

      Run: [ @repl.it ]

      from enigma import irange, isqrt, filter2, is_duplicate, arg, printf
      
      # Y = year the puzzle is set (which apparently should be 2018)
      Y = arg(2018, 0, int)
      # m = minimum allowable square (the root of the square is used)
      m = arg(2, 1, int)
      printf("[Y = {Y}, m={m}]")
      
      # squares (as strings, without repeated digits)
      (_, squares) = filter2(is_duplicate, (str(i * i) for i in irange(m, isqrt(Y))))
      
      # for Wunce find a pan-digital subset (without repeated digits)
      # ss = squares to consider
      # s = squares used so far
      # ds = digits used so far
      def solve1(ss, s=[], ds=set()):
        # are we done?
        if len(ds) == 10:
          yield list(int(x) for x in s)
        else:
          # chose the next element
          for (i, x) in enumerate(ss):
            if ds.intersection(x): continue
            yield from solve1(ss[i + 1:], s + [x], ds.union(x))
      
      # for Repete find a pan-digital set of squares (allowing repeated digits)
      # below a given total
      # n = largest square to consider
      # t = sum of squares must be less than this
      # s = squares used so far
      # ds = digits used so far
      def solve2(n, t, s=[], ds=set()):
        # are we done?
        if len(ds) == 10:
          yield s
        # choose the next element
        for i in irange(n, m, step=-1):
          i2 = i * i
          if i2 < t:
            yield from solve2(i - 1, t - i2, s + [i2], ds.union(str(i2)))
      
      # find sequences for Wunce
      for s1 in solve1(squares):
        t1 = sum(s1)
        printf("Wunce: total = {t1}, squares = {s1}")
      
        # calculate the age
        age = Y - t1
        age2 = age * age
        printf("age = {age}, age^2 = {age2}")
      
        # find sequences for Repete
        for s2 in solve2(age - 1, age2):
          t2 = sum(s2)
          printf("Repete: total = {t2}, squares = {s2}")
      

      Solution: The sum of Wunce’s squares is 1989. The sum of Repete’s squares is 831.

      Wunce’s list of squares is (324, 576, 1089) = (18², 24², 33²).

      The sum of which is 1989. So in 2018 the twins would be 29.

      Repete’s list of squares is (4, 9, 25, 36, 81, 100, 576) = (2², 3², 5², 6², 9², 10², 24²).

      The sum of which is 831. Which is less than 841 = 29².

      If we allow 1 in the list of squares then the sum of Repete’s list could be 832. And there are further possibilities if squares in the list are allowed to be repeated.


      The published solution is as follows:

      The sum of Wunce’s squares was 1989. We apologise that this Teaser needed to have been published in 2018 or later in order to resolve the sum of Repete’s squares (the intended answer was 831). All entries showing a correct answer for the first part of the Teaser will be included in the prize draw.

      Like

    • Frits's avatar

      Frits 1:43 pm on 20 October 2020 Permalink | Reply

      Same three assumptions.

      from enigma import nsplit, flatten
      from itertools import combinations as comb
      
      # contains all digits 0-9
      alldigits = lambda li: all(i in flatten([nsplit(x) for x in li]) 
                                 for i in range(0, 10))
      
      sq = [i*i for i in range(2, 45)]
      
      # check squares for Wunce
      for j in range(3, 6):
        # digit 7 only occurs first at sq[22] (576)
        # so pick some squares < 576 and at least one >= 576
        for j1 in range(1, j):
          for p1 in comb(sq[:22], j1):
            for p2 in comb(sq[22:], j - j1):
              p = p1 + p2
             
              if sum(p) not in range(1900, 2020): continue
              if sum(len(str(x)) for x in p) != 10: continue
              if not alldigits(p): continue
              
              age = 2018 - sum(p)
              limit = age * age
              
              space = limit - 576
              if space < 0: continue
              
              # we may only pick one or two squares from group 576, 625, ....
              fromHighest = 1 if space < 625 else 2
              
              # highest index with square smaller than limit and 2 smallest squares
              h2 = max([i for i, x in enumerate(sq) if x <= limit - 4 - 9])
              
              # check squares for Repete
              for k in range(3, 10):
               for j3 in range(1, fromHighest + 1):
                  for q2 in comb(sq[22:h2+1], j3):
                    picked = sum(q2)
                    # highest index with square smaller than limit minus q2 entries
                    h1 = max([i for i, x in enumerate(sq) if x <= limit - picked])
                    
                    for q1 in comb(sq[:h1+1], k - j3):
                      q = q1 + q2
                      if not alldigits(q): continue
                      if sum(q) >= age*age: continue
                      print("sum Wunce's", sum(p), p)
                      print("sum Repete's", sum(q), q)
                      print("Age", age)
      

      Like

  • Unknown's avatar

    Jim Randell 8:26 am on 15 October 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 505: [Colourland] 

    From The Sunday Times, 14th February 1971 [link]

    Colourland is inhabited by three races, all similar in appearance — Redmen, a truthful people; Greenmen, who always lie; and Bluemen, who sometimes tell the truth and sometimes lie. Their houses are painted either red, green or blue, but no one lives in a house with the colour of his race name.

    One day, after a football match, three of the winning team, which won 1-0, were standing together. Their shirts were numbered 1, 2 and 3, and by tradition these three would be one from each race, each occupying a different coloured house.

    I asked number 1 if number 2 told the truth more often than number 3, to which he answered “No”. I then asked number 2 if any of the three of them had scored the winning goal, his reply being “I did”.

    I next asked one of them if he lived in a certain coloured house, and from his reply I was in fact able to determine:

    (i) the colour of each tribesman’s house, and:
    (ii) which (if any) scored the goal.

    Can you?

    This puzzle was originally published with no title.

    [teaser505]

     
    • Jim Randell's avatar

      Jim Randell 8:27 am on 15 October 2019 Permalink | Reply

      The tribes on the island are described as “similar in appearance”, which I take to mean that the setter is not able to determine which tribe the person he is questioning is from, other than from the answers to the questions.

      This Python program runs in 84ms.

      from enigma import (subsets, cproduct, join, printf)
      
      # honesty rating
      h = dict(R=2, B=1, G=0)
      
      # valid replies for tribe t, statement s
      def valid(t, s):
        s = bool(s)
        if t == "R": return s
        if t == "G": return (not s)
        return True
      
      # collect responses
      rs = list()
      
      # assign tribes
      for (t1, t2, t3) in subsets("RGB", size=len, select="P"):
      
        # check statement: "Is 2 more truthful than 3?" -> 1: "No"
        if not valid(t1, not (h[t2] > h[t3])): continue
      
        # choose a goal scorer
        for g in (0, 2):
      
          # check statement: "Who scored the winning goal?" -> 2: "2"
          if not valid(t2, g == 2): continue
      
          # assign houses
          for (h1, h2, h3) in subsets("RGB", size=len, select="P"):
            # no one lives in the same colour house as his tribe
            if t1 == h1 or t2 == h2 or t3 == h3: continue
      
            rs.append(((t1, t2, t3), (h1, h2, h3), g))
      
      
      # Q3 to player P: "Is the colour of your house Q?"
      for (P, Q) in cproduct([(1, 2, 3), "RGB"]):
        i = P - 1 # index for player P
      
        # collect results
        (ys, ns) = (set(), set())
        for (tribes, houses, g) in rs:
      
          # solution is (house colours by tribe, goal scorer)
          s = (tuple(x + houses[tribes.index(x)] for x in "RGB"), ("2" if g == 2 else "not 2"))
      
          # answer is "Yes"
          if valid(tribes[i], houses[i] == Q):
            ys.add(s)
      
          # answer is "No"
          if valid(tribes[i], houses[i] != Q):
            ns.add(s)
      
        # examine the responses
        for (s, t) in zip([ys, ns], ["Yes", "No"]):
          # we only want one
          if len(s) != 1: continue
          (hs, g) = s.pop()
          # and the goal scorer must be determined
          if g.startswith("not "): continue
          # output solution
          printf("Q3 to player {P}: \"Is your house {Q}?\"; {t} -> houses = {hs}; scorer = {g}", hs=join(hs, sep=" "))
      

      Solution: Yes. (i) Redman in blue house. Blueman in green house. Greenman in red house; (ii) Redman scored the goal.

      The third question is asked of player 2, and is: “Is your house green?”.

      An answer of “No” allows the questioner to infer:

      Player 2 is Redman. His house is blue. He scored the goal.
      Player 1 and 3 are: Greenman in a red house and Blueman in a green house, but we don’t know which player has which number.

      Similarly, if the third question asked (still of player 2) is: “Is your house red?”, and the answer received is “Yes”, then we can infer:

      Player 2 is Greenman. His house is blue. He did not score the goal.
      Player 1 and 3 are: Redman in a green house and Blueman in a red house, but we don’t which player has which number.

      But we cannot determine who the goal scorer is, only that it isn’t player 2.


      If we consider the first question.

      If the person we ask is Blue, then they could answer anything. So the following are possible:

      #1=B, #2=R, #3=G
      #1=B, #2=G, #3=R

      If the person asked the first question is Red, then #2 does not tell the truth more often than #3:

      #1=R, #2=G, #3=B

      If the person asked the first question is Green, then #2 does tell the truth more often than #3:

      #1=G, #2=R, #3=B

      So there are four possible assignments of players to tribes, and #2 is not Blue, so we can ask them a question, and know we are not going to get a “random” answer.

      If we ask #2 “Do you live in a green house?”. We know if G is asked this they must answer “Yes” (as they don’t), so if we get an answer of “No” we know that #2 must be R, and they do not live in a green house.

      In this situation the houses are: RB, BG, GR, and we also know that R is #2, and so answered Q2 truthfully, so R scored the goal.

      Like

  • Unknown's avatar

    Jim Randell 9:54 am on 14 October 2019 Permalink | Reply
    Tags:   

    Teaser 2826: By heck! 

    From The Sunday Times, 20th November 2016 [link] [link]

    The registration number of my old car consists of three consecutive letters of the alphabet in reverse order, followed by a three-figure number consisting of the same digit written three times, followed finally by a single letter.

    I am a fan of “hex” (i.e. arithmetic in base 16, with “digits” 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E and F) and I realised that the registration number looked like a number in hex. So I worked out its equivalent value in our usual base-10 arithmetic. Miraculously the answer was a nine-figure number that used all nine of the non-zero digits.

    What is the registration number?

    [teaser2826]

     
    • Jim Randell's avatar

      Jim Randell 9:55 am on 14 October 2019 Permalink | Reply

      The number plate reads as the following hex digits abcdefg, where:

      a = b + 1
      b = c + 1
      c > 9
      d = e = f < 10
      g > 9

      So there are 4 × 10 × 6 = 240 possibilities for the registration number which can be examined by a straightforward program to find those which correspond to an appropriate decimal number.

      This Python program runs in 47ms.

      Run: [ @repl.it ]

      from enigma import (irange, cproduct, nconcat, nsplit, int2base, printf)
      
      # consider possible hex digits
      for (x, y, z) in cproduct([irange(10, 13), irange(0, 9), irange(10, 15)]):
        # calculate the numerical value of the number plate (as hex)
        n = nconcat((x + 2, x + 1, x, y, y, y, z), base=16)
        # split n into base 10 digits
        ds = nsplit(n, base=10)
        # there should be 9 different digits, not including 0
        if len(ds) == 9 and 0 not in ds and len(set(ds)) == 9:
          # output solution
          printf("{h} hex = {n} dec", h=int2base(n, base=16))
      

      Solution: The registration number is CBA777F.

      Like

  • Unknown's avatar

    Jim Randell 3:03 pm on 11 October 2019 Permalink | Reply
    Tags:   

    Teaser 2977: Enjoying retirement 

    From The Sunday Times, 13th October 2019 [link] [link]

    George and Martha have worked on separate departments of a company which has four-digit telephone extensions. George looked at his extension and it was ABCD. Martha’s (larger) also had A, B and C as her first three digits but not necessarily in that order. Her last digit was E. They added up their two four-digit numbers and found that the least significant digit was F. They then looked at the difference and that was a four-digit number of which the least significant digit was G. They then looked at the product and the least significant digit was H. They then looked at the average of the extensions; in it the first two digits were equal, the last two digits were also equal, and the least significant digit was J. I have thus mentioned nine digits, all positive and unequal.

    What was Martha’s extension?

    [teaser2977]

     
    • Jim Randell's avatar

      Jim Randell 3:34 pm on 11 October 2019 Permalink | Reply

      I assumed that the average of the two extension numbers was a whole number, so both extension numbers must have the same parity.

      The following Python program runs in 92ms.

      Run: [ @repl.it ]

      from enigma import (irange, subsets, nconcat, nsplit, div, printf)
      
      # allowable digits
      digits = set(irange(1, 9))
      
      # check digits are allowable and all different
      def check(*ds):
        return len(ds) + len(digits.difference(ds)) == len(digits)
      
      # consider digits D and E, which must have the same parity
      for (D, E) in subsets(digits, size=2, select='P'):
        if not(D % 2 == E % 2): continue
      
        # the sum ends in F, difference ends in G, the product ends in H
        (F, G, H) = (n % 10 for n in (D + E, E - D, D * E))
        if not check(D, E, F, G, H): continue
      
        # choose first three digits A, B, C to give ABCD = George's extension
        for (A, B, C) in subsets(digits.difference((D, E, F, G, H)), size=3, select='P'):
          xG = nconcat(A, B, C, D)
      
          # and permute ABC to give XYZ, where XYZE = Martha's extension
          for (X, Y, Z) in subsets((A, B, C), size=3, select='P'):
            xM = nconcat(X, Y, Z, E)
      
            # George's number is less than Martha's, difference is 4 digits
            if xM - xG < 1000: continue
      
            # average ...
            avg = nsplit(div(xG + xM,  2))
            # has first 2 and last 2 digits equal
            if not(avg[0] == avg[1] and avg[-2] == avg[-1]): continue
            # and the final digit is J
            J = avg[-1]
            if not check(A, B, C, D, E, F, G, H, J): continue
      
            printf("George = {xG}, Martha = {xM} [A={A} B={B} C={C} D={D} E={E} F={F} H={H} J={J}]")
      

      Solution: Martha’s extension number is 8563.

      George’s extension number is 6859.

      So if George’s number is ABCD, then Martha’s is BCAE.

      The sum is 15422, which ends in F=2.

      The difference is 1704, which ends in G=4.

      The product is 58733617, which ends in H=7.

      And the average (mean) is 7711, which starts with two 7’s and ends with two J’s; J=1.

      Each non-zero digit is mentioned once. We have (1, 2, 3, 4, 5, 6, 7, 8, 9) = (J, F, E, G, C, A, H, B, D).

      Like

    • GeoffR's avatar

      GeoffR 9:31 am on 13 October 2019 Permalink | Reply

      
      % 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;    
      var 1..9: G; var 1..9: H; var 1..9: J;
      
      constraint all_different([A, B, C, D, E, F, G, H, J]);
      
      % George's extension number
      var 1000..9999: george = 1000*A + 100*B + 10*C + D; 
      
      % Martha's extension number
      var 1000..9999: martha ;
      
      % Average of George's and Martha's numbera
      var 1000..9999: av ; 
       
      constraint av == (martha + george) div 2;
      constraint martha > george;
      
      % Martha's extension had the first three digits A,B,C in some order
      % Martha's 1st Digit
      constraint 
         martha div 1000 == A 
      \/ martha div 1000 == B 
      \/ martha div 1000 == C;
      
      % Martha's 2nd Digit
      constraint 
         ((martha div 100) mod 10) == A
      \/ ((martha div 100) mod 10) == B
      \/ ((martha div 100) mod 10) == C;
      
      % Martha's 3rd Digit
      constraint 
         ((martha div 10) mod 10) == A
      \/ ((martha div 10) mod 10) == B
      \/ ((martha div 10) mod 10) == C;
      
      % Martha's 4th Digit
      constraint martha mod 10 == E;
      
      % Sum of george and martha has F as least significant digit
      constraint (george + martha) mod 10 == F;
      
      % Difference of george and martha has G as least significant digit
      constraint (martha - george) > 1000  
      /\ (martha - george) mod  10 == G;
      
      % Product of george and martha has H as least significant digit
      constraint (martha * george) mod 10 == H;
      
      % Average has first 2 digits equal
      constraint av div 1000 ==  (av div 100) mod 10;
        
      % Average has last 2 digits equal to J
      constraint (av div 10) mod 10 == J /\ av mod 10 = J;
      
      solve satisfy;
      
      output [ "Martha's extension is " ++ show(martha) 
      ++ "\n" ++ "George's extension is " ++ show(george)
      ++ "\n" ++ "Average of two extensions is " ++ show(av)];
      
      % Martha's extension is 8563
      % George's extension is 6859
      % Average of two extensions is 7711
      % ----------
      % ==========
      
      

      Like

  • Unknown's avatar

    Jim Randell 10:38 am on 11 October 2019 Permalink | Reply
    Tags:   

    Teaser 2829: Making a dozen 

    From The Sunday Times, 11th December 2016 [link]

    In this addition sum different letters consistently stand for different digits:

    What is the value of LETTERS?

    [teaser2829]

     
    • Jim Randell's avatar

      Jim Randell 10:39 am on 11 October 2019 Permalink | Reply

      This is a straightforward alphametic sum.

      We can solve it using the [[ SubstitutedSum() ]] solver from the enigma.py library.

      The following command executes in 164ms.

      % python -m enigma SubstitutedSum "SEVEN + THREE + TWO = TWELVE"
      (SEVEN + THREE + TWO = TWELVE)
      (82524 + 19722 + 106 = 102352) / E=2 H=9 L=3 N=4 O=6 R=7 S=8 T=1 V=5 W=0
      (82526 + 19722 + 104 = 102352) / E=2 H=9 L=3 N=6 O=4 R=7 S=8 T=1 V=5 W=0
      

      Solution: LETTERS = 3211278.

      The values for N and O can be interchanged, but we are asked for the value of LETTERS, so the solution is unique.

      Like

    • GeoffR's avatar

      GeoffR 11:01 am on 12 October 2019 Permalink | Reply

      
      % A Solution in MiniZinc
      
      %   S E V E N
      %   T H R E E
      %       T W O
      % -----------
      % T W E L V E
      % -----------
      include "globals.mzn";
       
      var 1..9:S; var 0..9:E; var 0..9:V; var 0..9:N;
      var 1..9:T; var 0..9:H; var 0..9:R; var 0..9:W;   
      var 0..9:O; var 0..9:L;
      
      % Carry digits for adding columns
      var 0..2: carry1; var 0..2: carry2; var 0..2: carry3; 
      var 0..2: carry4; var 0..2: carry5; 
       
      constraint all_different([S, E, V, N, T, H, R, W, O, L]);
      
      % Working left from the right hand column
      constraint (N + E + O) mod 10 == E 
      /\ (N + E + O) div 10 == carry1;
      
      constraint (2*E + W + carry1) mod 10 == V 
      /\ (2*E + W + carry1) div 10 == carry2;
      
      constraint (V + R + T + carry2) mod 10 == L 
      /\ (V + R + T + carry2) div 10 == carry3;
      
      constraint (E + H + carry3) mod 10 == E 
      /\ (E + H + carry3) div 10 == carry4;
      
      constraint (S + T + carry4) mod 10 == W 
      /\ (S + T + carry4) div 10 == carry5;
      
      constraint T = carry5;
      
      solve satisfy;
      
      output [ "LETTERS = " ++ show(L),show(E),
      show(T),show(T),show(E), show(R),show(S) ]
      
      ++ ["\n" ++ "SEVEN = " ++  show(S),show(E),
      show(V),show(E),show(N)]
      ++ [", THREE = " ++  show(T),show(H),show(R),
      show(E),show(E) ]
      ++ [", TWO = " ++  show(T),show(W),show(O) ]
      ++ [", TWELVE = " ++  show(T),show(W),show(E),
      show(L),show(V),show(E)];
      
      % LETTERS = 3211278
      % SEVEN = 82526, THREE = 19722, TWO = 104, TWELVE = 102352
      % -----------------
      % LETTERS = 3211278
      % SEVEN = 82524, THREE = 19722, TWO = 106, TWELVE = 102352
      % Finished in 161msec
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 11:51 am on 9 October 2019 Permalink | Reply
    Tags:   

    Teaser 2836: Squaring up 

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

    Alice had a large collection of one centimetre square tiles. She used them to make a set of some larger squares of different sizes, all with sides of less than a metre. When I saw these squares I removed one corner tile from each. Then, for each mutilated shape, Alice moved the minimum number of tiles to transform it into a rectangle. Overall she moved two hundred tiles. This resulted in a set of rectangles all of whose sides were a prime number of centimetres long.

    What (in increasing order) were the lengths of the sides of her original squares?

    [teaser2836]

     
    • Jim Randell's avatar

      Jim Randell 11:51 am on 9 October 2019 Permalink | Reply

      If Alice has made a square of side n (so n < 100), then she has used n² tiles.

      The setter removes one corner tile from the square, leaving (n² − 1) tiles.

      Alice can then take the remaining (n − 1) tiles from the same row (or column) as the removed tile, to produce a rectangle with dimensions n × (n − 1), and the removed (n − 1) tiles can be added back to form an additional column (or row) of a rectangle with dimensions (n + 1) × (n − 1).

      We require both these dimensions to be prime, so we are looking for twin primes of the form (n − 1) and (n + 1).

      We need to find a set of primes that sum to 200, where each is the lower of a pair of twin primes.

      This Python program runs in 85ms.

      Run: [ @repl.it ]

      from enigma import (primes, tuples, subsets, printf)
      
      # find possible shapes, record p
      ps = list(p for (p, q) in tuples(primes.between(1, 100), 2) if q == p + 2)
      
      # find a subset that sums to 200
      for s in subsets(ps, min_size=3):
        if sum(s) == 200:
          # the sides of the original squares
          ns = list(p + 1 for p in s)
          printf("squares = {ns}")
      

      Solution: The lengths of the sides of the original squares were: 30, 42, 60, 72.


      Examining all subsets could be a costly approach if the parent set is large. In this case there are only 8 candidate primes, so there are at most 255 (non-empty) subsets to consider.

      So here is an alternative program, although on a small problem like this there isn’t much difference in execution time.

      from enigma import (primes, tuples, printf)
      
      # find possible shapes, record p
      ps = list(p for (p, q) in tuples(primes.between(1, 100), 2) if q == p + 2)
      
      # decompose <t> into numbers from <ns>
      def decompose(t, ns, s=[]):
        if t == 0:
          yield s
        else:
          for (i, n) in enumerate(ns):
            if n > t: break
            yield from decompose(t - n, ns[i + 1:], s + [n])
      
      # find a subset that sums to 200
      for s in decompose(200, ps):
        # the sides of the original squares
        ns = list(p + 1 for p in s)
        printf("squares = {ns}")
      

      Like

  • Unknown's avatar

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

    Brainteaser 1730: Not so usual 

    From The Sunday Times, 12th November 1995 [link]

    As usual Eric was early for his morning train. Two express trains of the same length passed through the station in opposite directions, each at its own constant speed. Out of interest Eric timed them and noted that the faster one took 6 seconds to pass him, while the slower one took 8 seconds.

    As soon as they had passed he saw his travelling companion, Len, 30 yards along the platform. In his conversation later, Eric told Len that he had been standing exactly in line with the point at which the fronts of the trains coincided.

    Len then commented that, by coincidence, he had been standing exactly in line with the point at which the ends of the trains coincided. Eric was delighted because he was now able to work out the speeds of the trains.

    How long were the trains?

    This puzzle is included in the book Brainteasers (2002), under the title “Commuter computer”. The puzzle text above is taken from the book.

    [teaser1730]

     
    • Jim Randell's avatar

      Jim Randell 8:11 am on 8 October 2019 Permalink | Reply

      At time 0s the fronts of the two trains (each of length x yards) are in line with Eric.

      At time 6s, the faster train’s end passes Eric. So it is travelling at (x/6) yards/s.

      At time 8s, the slower train’s end passes Eric. So it is travelling at (x/8) yards/s.

      The ends of the trains pass each other (and Len) at time t, when the faster train has travelled its entire length plus 30 yards, and the slower train has travelled its entire length less 30 yards.

      So:

      tx/6 = x + 30
      tx/8 = x − 30

      These equations are solved to give:

      x = 210, t = 48/7

      Solution: The trains were 210 yards long.

      So the faster train is travelling at 35 yards/s (about 72 mph) and the slower train is travelling at 26.25 yards/s (about 54 mph).

      And the ends of the trains passed each other (and Len) 6/7 seconds after the end of the fastest train passed Eric.

      Like

  • Unknown's avatar

    Jim Randell 8:18 am on 7 October 2019 Permalink | Reply
    Tags:   

    Teaser 2837: Back and forth 

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

    George and Martha have a digital 24-hour clock that always displays the time as four digits (e.g. 2:17am displays as 0217). During one lazy weekend George noted two particular times when the four-digit display was palindromic. He calculated the number of minutes from the first of these times to the second and he discovered that the answer was a three-figure palindrome. When he reported all the details to Martha, she commented that the sum of the eleven digits in the three palindromes was also palindromic.

    What were the two palindromic times?

    [teaser2837]

     
    • Jim Randell's avatar

      Jim Randell 8:19 am on 7 October 2019 Permalink | Reply

      This program considers when there is a corresponding minute for each hour to make a list of palindromic times, and then looks at pairs of times from this list that satisfy the remaining conditions.

      It runs in 44ms.

      from itertools import product
      from enigma import (irange, nsplit, concat, printf)
      
      # palindrome check
      is_palindrome = lambda s: s[::-1] == s
      
      # record palindromic times
      ts = list()
      for h in irange(0, 23):
        (a, b) = nsplit(h, 2)
        m = 10 * b + a
        # record time (in minutes) and displayed digits
        if m < 60: ts.append((h * 60 + m, (a, b, b, a)))
      
      # now consider two palindromic times (the second time could be the following day)
      for ((t1, ds1), (t2, ds2), t3) in product(ts, ts, (0, 1440)):
      
        # calculate the difference in minutes
        t = t2 + t3 - t1
      
        # it should be a 3-digit palindrome
        if not (99 < t < 1000): continue
        ds = nsplit(t)
        if not is_palindrome(ds): continue
      
        # calculate the sum of the digits, it should also be a palindrome
        s = sum(ds1) + sum(ds2) + sum(ds)
        if not is_palindrome(nsplit(s)): continue
      
        # output a solution
        printf("{ds1} -> {ds2}{x} = {t} minutes, digit sum = {s}", ds1=concat(ds1), ds2=concat(ds2), x=(" (next day)" if t3 else ""))
      

      Solution: The two times were 1001 and 0110 (the following day).

      The first time is 10:01am on one day (displayed as 1001), the second time is 1:10am the following day (displayed as 0110). The difference between these times is 15 hours and 9 minutes = 909 minutes. And the sum of the digits in 1001, 0110, 909 is 22.

      Like

    • Frits's avatar

      Frits 11:08 am on 22 December 2020 Permalink | Reply

      Slow solution compared to a similar program with enigma.py’s SubstitutedExpression (resp. 600 ms and 15 ms).

      % A Solution in MiniZinc
      
      % time1 ABBA time2 CDDC
      var 0..2:A; var 0..5:B; var 0..2:C; var 0..5:D; 
      var 1..9:E; var 0..9:F; 
      var 1..4:G;
      var 0..23: AB = 10*A + B; var 0..59: BA = 10*B + A;
      var 0..23: CD = 10*C + D; var 0..59: DC = 10*D + C;
      var 101..999: EFE = 101*E + 10*F;
       
      % difference in minutes time1 ABBA time2 CDDC
      constraint (CD * 60 + DC - (AB * 60 + BA) + 1440) mod 1440 == EFE;              
      
      % sum of the eleven digits in the three palindromes was also palindromic
      constraint 2 * ( A + B + C + D + E) + F == G * 11;
       
      solve satisfy;
       
      output ["Time 1 = " ++ show(A) ++ show(B) ++ ":" ++ show(B) ++ show(A) ++ 
      ", Time 2 = " ++ show(C) ++ show(D) ++ ":" ++ show(D) ++ show(C) ++
      ", Difference  = " ++ show(EFE) ++ ", Sum = " ++ show(G * 11)];
       
      % Time 1 = 10:01, Time 2 = 01:10, Difference  = 909, Sum = 22
      % ----------
      % ==========
      

      Like

  • Unknown's avatar

    Jim Randell 8:58 am on 6 October 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 504: [Scrumps competition] 

    From The Sunday Times, 7th February 1971 [link]

    The inter-house Scrumps competition has just ended at Marlinghurst School. The four houses play each other once and the scoring is on a league basis (win 2, draw 1, lose 0). Arne played Bach in the 1st round, Chopin in the 2nd and Debussy in the 3rd.

    In the 1st round no two houses scored the same number of “scrumps” (a scrump is a sort of goal scored by forcing an opponent through a hole in the wall).

    In the 2nd and 3rd rounds every house scored exactly twice as many scrumps as its current opponent had scored in the previous round.

    Chopin and Debussy tied on points, but a better scrump average (i.e. ratio of scrumps for to scrumps against) gave Debussy the Pergolesi Bowl. Arne and Bach also tried, but Arne’s lower scrump average put them fourth in the final table.

    Although the total number of scrumps scored in the competition fell short of the school record (55) it was higher than last year’s total (44).

    What was:

    (a) Arne’s scrump average?
    (b) the score in the Bach-Chopin match?

    This puzzle was originally published with no title.

    [teaser504]

     
    • Jim Randell's avatar

      Jim Randell 9:00 am on 6 October 2019 Permalink | Reply

      If we know the scores in the first round (say: a, b, c, d scrumps, scored by A, B, C, D respectively), then the scores in each match are:

      (1) A vs B = a – b; C vs D = c – d
      (2) A vs C = 2c – 2a; B vs D = 2d – 2b
      (3) A vs D = 4b – 4c; B cs C = 4a – 4d

      So the total number of scrumps scored is: 7(a + b + c + d).

      And this lies between 44 and 55, so it must be 49, hence a + b + c + d = 7, and the individual totals must be 0, 1, 2, 4 in some order.

      This Python program runs in 86ms.

      from enigma import (compare, subsets, printf)
      
      # points for team X in the X vs Y match, if the score if x - y
      pts = lambda x, y: compare(x, y, vs=(0, 1, 2))
      
      # consider possible scores in round 1
      for (a1, b1, c1, d1) in subsets((0, 1, 2, 4), size=len, select="P"):
        # calculate the scores in the other rounds
        (a2, b2, c2, d2) = (2 * x for x in (c1, d1, a1, b1))
        (a3, b3, c3, d3) = (2 * x for x in (d2, c2, b2, a2))
      
        # calculate the points
        A = pts(a1, b1) + pts(a2, c2) + pts(a3, d3)
        B = pts(b1, a1) + pts(b2, d2) + pts(b3, c3)
        C = pts(c1, d1) + pts(c2, a2) + pts(c3, b3)
        D = pts(d1, c1) + pts(d2, b2) + pts(d3, a3)
        # C and D tied on points for 1st/2nd
        # A and B tied on points for 3rd/4th
        if not (C == D and A == B and C > A): continue
      
        # calculate goals for/against
        (fA, aA) = (a1 + a2 + a3, b1 + c2 + d3)
        (fB, aB) = (b1 + b2 + b3, a1 + d2 + c3)
        (fC, aC) = (c1 + c2 + c3, d1 + a2 + b3)
        (fD, aD) = (d1 + d2 + d3, c1 + b2 + c3)
        # D had a better average than C
        # B had a better average than A
        if not (fD * aC > fC * aD and fB * aA > fA * aB): continue
      
        # output solution
        printf("(a) {fA}/{aA}; (b) {b3}-{c3}; [a={a1} b={b1} c={c1} d={d1}; A={A} B={B} C={C} D={D}]")
      

      Solution: (a) Arne’s scrump average was: 12/17 (≈ 0.71); (b) The score in the Bach-Chopin match was 16 – 0.

      The scores in the three rounds were:

      (1) A vs B = 4 – 1; C vs D = 2 – 0
      (2) A vs C = 4 – 8; B vs D = 0 – 2
      (3) A vs D = 4 – 8; B cs C = 16 – 0

      Like

  • Unknown's avatar

    Jim Randell 5:11 pm on 4 October 2019 Permalink | Reply
    Tags:   

    Teaser 2976: Piece of cake 

    From The Sunday Times, 6th October 2019 [link] [link]

    Using her special recipe, so that each cubic inch of baked cake weighed one ounce, Mam made the cake for my eighth birthday party. It had a regular octagonal flat top and base, and equal square vertical faces, several inches high exactly.

    Not all (but a majority) of the dozen invited pals came to the party. We each had an equal portion of cake (the largest whole number of ounces possible from it, a two-figure number). Mam had the leftover cake. Curiously, if one more or one fewer pal had turned up and our portions had been worked out in the same way, Mam’s leftover would have been the same in each case, but less than she actually got.

    How large, in ounces, was my portion?

    [teaser2976]

     
    • Jim Randell's avatar

      Jim Randell 5:38 pm on 4 October 2019 Permalink | Reply

      12 people were invited, and more than half but not all came, so between 7 and 11. If we include the setter as well the cake is divided into between 8 and 12 integer portions.

      We can ignore the fractional part of the volume as it is always included in the leftover portion of cake. So we just need to consider the integer part of the remaining portion.

      This Python program runs in 87ms.

      from enigma import (sqrt, irange, inf, divf, printf)
      
      # area of an octagon with unit sides
      a = 2 * (1 + sqrt(2))
      
      # consider the side of the octagon
      for x in irange(1, inf):
        # volume of the cake (discarding the fractional part)
        v = int(a * x**3)
        if v < 80: continue
        if v > 1200: break
      
        # consider the number of portions
        d = dict()
        for k in irange(7, 13):
          # the (2-digit) amount of cake per portion, and remaining amount
          (p, r) = divmod(v, k)
          if 9 < p < 100: d[k] = r
      
        # find the actual number of portions
        for (k, r) in d.items():
          try:
            (rm, rp) = (d[k - 1], d[k + 1])
          except KeyError:
            continue
          if not (rm < r and rm == rp): continue
          # output solution
          printf("portion = {p} [x={x} k={k}; ({km} -> {rm}+, {k} -> {r}+, {kp} -> {rp}+)]", p=divf(v, k), km=k - 1, kp=k + 1)
      

      Solution: The portion size was 54 ounces.

      It seems like quite a large portion, but I suppose any 2-digit number of ounces is quite a weighty piece of cake.

      Of the 12 invited guests, 10 attended, meaning that the cake was divided into 11 integer portions.

      The cake has vertical faces that are squares measuring 5 inches along each side, so would require a round cake tin just over 13 inches in diameter to fit it in. It would weigh just over 603.5 ounces (about 17.1 kg).


      We only need to look at the cases where the cake is between 3 and 6 inches high, and there are four possibilities where the leftover portions would have been equal if one fewer or one more guest had attended:

      height = 3″, portions = 8 @ 16 oz, leftover = 2.37 oz; 7 or 9 portions, leftover = 4.37 oz
      height = 4″, portions = 11 @ 28 oz, leftover = 1.02 oz; 10 or 12 portions, leftover = 9.02 oz
      height = 5″, portions = 9 @ 67 oz, leftover = 0.55 oz; 8 or 10 portions, leftover = 3.55 oz
      height = 5″, portions = 11 @ 54 oz, leftover = 9.55 oz; 10 or 12 portions, leftover = 3.55 oz

      Only the last of these has a hypothetical leftover portion that is smaller than the actual leftover portion, so this gives rise to the solution.

      Like

  • Unknown's avatar

    Jim Randell 9:52 am on 4 October 2019 Permalink | Reply
    Tags:   

    Teaser 2840: Signs of the times 

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

    I was taking a gentle morning drive along the straight road to Secombe that passes through Firsk. Before reaching Firsk I passed three signposts, each giving the distances to Firsk and to Secombe (to the nearest mile). All six distances displayed were different and, amazingly, all were perfect squares [less than 100].

    What were the two distances given on the first signpost (furthest from Firsk)?

    I have added the “less than 100” condition to reduce ambiguity in the puzzle.

    [teaser2840]

     
    • Jim Randell's avatar

      Jim Randell 9:54 am on 4 October 2019 Permalink | Reply

      When this puzzle was first published there was some confusion over the correct interpretation. I have added the condition to require the squares to be less than 100 to eliminate multiple solutions.

      The distances on the signposts are rounded to the nearest mile. This Python program uses intervals to find viable solutions. It runs in 47ms.

      Run: [ @repl.it ]

      from enigma import (irange, isqrt, subsets, arg, printf)
      
      # limit to numbers on signs
      M = arg(100, 0, int)
      printf("[M={M}]")
      
      # possible squares that can appear on the signs
      squares = list(i * i for i in irange(1, isqrt(M - 1)))
      
      # possible distances for three signs (in order)
      signs = subsets(squares, size=3)
      
      # combine lower/upper bounds into an interval
      def interval(v, *vs):
        (l, u) = v
        for (l1, u1) in vs:
          (l, u) = (max(l, l1), min(u, u1))
        return (l, u)
      
      # choose the distances to F and S on the signs
      for ((f1, f2, f3), (s1, s2, s3)) in subsets(signs, size=2):
      
        # check the distances are all different
        if len({f1, f2, f3, s1, s2, s3}) < 6: continue
      
        # calculate the position of S
        (sl, su) = interval(
          (s1 - f1 - 1, s1 - f1 + 1),
          (s2 - f2 - 1, s2 - f2 + 1),
          (s3 - f3 - 1, s3 - f3 + 1),
        )
      
        # is it feasible?
        if 0 < sl < su:
          printf("signs = ({f1} {s1}) ({f2} {s2}) ({f3} {s3}), F -> S = ({sl}, {su})")
      

      Solution: The distances on the first signpost encountered were 49 miles (to Firsk) and 64 miles (to Secombe).

      The distance between F and S is between 15 and 16 miles.

      So if, for example, the distance between F and S was 15.2 miles, and the signposts are at distances of 1.2 miles, 9.4 miles and 48.6 miles from F, then they would read:

      1.2 miles from F, 16.4 miles from S: “F 1, S 16”
      9.4 miles from F, 24.6 miles from S: “F 9, S 25”
      48.6 miles from F, 63.8 miles from S: “F 49, S 64”

      Without the restriction on the squares there are further solutions that use distances of 100 and 121 (and higher values):

      signs = (4, 25) (16, 36) (100, 121); F to S = 20 – 21 miles
      signs = (9, 49) (25, 64) (81, 121); F to S = 39 – 40 miles

      And with even higher values we can solve the puzzle using exact distances:

      signs = (1, 49) (16, 64) (121, 169); F to S = 48 miles

      Like

  • Unknown's avatar

    Jim Randell 3:51 pm on 3 October 2019 Permalink | Reply
    Tags:   

    Brainteaser 1724: Like a lamb 

    From The Sunday Times, 1st October 1995 [link]

    Mary had a little lamb,
    Its fleece was white as snow
    And everywhere that Mary went
    The lamb was sure to go.

    It followed her to school one day,
    But found the maths a bore,
    For lambs, you see, do all their counting
    On a scale of four.

    Thus when a lamb writes two times two
    Its answer looks like 10,
    While our 10 written by a lamb
    Is double-2 again!

    It much distressed them both to find
    They never could agree
    On how to write down any
    Of the numbers after three.

    At last they hit on some for which
    The lamb would only need
    Two figures placed in front of Mary’s,
    Then they were agreed.

    Which two figures?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1724]

     
    • Jim Randell's avatar

      Jim Randell 3:52 pm on 3 October 2019 Permalink | Reply

      We are to infer from the puzzle text that the lamb counts using base 4, with the standard symbols 0, 1, 2, 3.

      So we need to find numbers in base 4 whose representation in base 10 is the same as the representation in base 4 but with the leftmost 2 digits removed.

      This Python program runs in 221ms.

      Run: [ @repl.it ]

      from enigma import irange, inf, nsplit, nconcat, printf
      
      # base 4 digits for number n
      base4 = lambda n: nsplit(n, base=4)
      
      # consider k-digit base 4 numbers, read as base 10 numbers, they need to be (k + 2) digits
      for k in irange(1, inf):
        # smallest k-digit base 4 number read as a base 10 number
        if len(base4(10 ** (k - 1))) > k + 2: break
        # largest k-digit base 4 number read as a base 10 number
        if len(base4((10 ** k - 1) // 3)) < k + 2: continue
      
        # consider possible (k + 2) digit base 4 numbers 
        for n in irange(4 ** (k + 1), 4 ** (k + 2) - 1):
          # represented in base 4
          ds = base4(n)
          # does removing the first two digits give the base 10 representation?
          if nconcat(ds[2:]) == n:
            printf("prefix = {p} [k={k}: {ds} (base 4) = {n} (base 10)]", p=nconcat(ds[:2]), ds=nconcat(ds))
      

      Solution: The 2-digit prefix is 30.

      The only viable numbers are:

      303320 (base 4) = 3320 (base 10)
      303321 (base 4) = 3321 (base 10)
      303322 (base 4) = 3322 (base 10)
      303323 (base 4) = 3323 (base 10)

      The program considers base 4 numbers that are 5-, 6- and 7-digits long, and looks for corresponding 3-, 4- and 5- digit base 10 numbers.

      Like

  • Unknown's avatar

    Jim Randell 9:11 am on 1 October 2019 Permalink | Reply
    Tags:   

    Brain-Teaser 503: [Exam marks] 

    From The Sunday Times, 31st January 1971 [link]

    When the headmaster came to look up Charley’s marks in the previous term’s exam in Physics and Chemistry, sat by the Science pupils of the 6th (Al, Bill, Charley, Dan, Ed, Frank and George) he found that ink had been spilt on the results sheet and only the following was legible:

    He remembered that the pupils finished in alphabetical order in total marks; that there were no ties in either subject, or overall; and that no pupil occupied the same place in each subject.

    All that he could remember about Charley’s results was that he was placed higher in Chemistry than in Physics.

    What were Charley’s marks in each subject?

    This puzzle was originally published with no title.

    [teaser503]

     
    • Jim Randell's avatar

      Jim Randell 9:13 am on 1 October 2019 Permalink | Reply

      I assumed the exams are marked out of 100, and only whole numbers of marks are awarded.

      I made a MiniZinc model for the puzzle. It finds a single solution in 121ms.

      %#! minizinc --solver chuffed --all
      
      include "globals.mzn";
      
      % label the boys
      set of int: Boys = 1..7;
      int: A = 1;
      int: B = 2;
      int: C = 3;
      int: D = 4;
      int: E = 5;
      int: F = 6;
      int: G = 7;
      
      % places for each boy in each subject
      array [Boys] of var 1..7: pPh;
      array [Boys] of var 1..7: pCh;
      
      constraint all_different(pPh);
      constraint all_different(pCh);
      
      % marks for each boy in each subject
      array [Boys] of var 0..100: mPh;
      array [Boys] of var 0..100: mCh;
      
      constraint forall (x, y in Boys where x != y) ((pPh[x] < pPh[y]) -> (mPh[x] > mPh[y]));
      constraint forall (x, y in Boys where x != y) ((pCh[x] < pCh[y]) -> (mCh[x] > mCh[y]));
      
      % given values
      constraint pPh[A] = 5;
      constraint pCh[B] = 2;
      constraint pPh[E] = 3;
      constraint pCh[G] = 5;
      constraint mPh[D] = 70;
      constraint mCh[F] = 67;
      constraint mPh[G] = 71;
      
      % total marks is 1023
      constraint sum (x in Boys) (mCh[x] + mPh[x]) = 1023;
      
      % "the pupils finished in alphabetical order by total marks"
      constraint decreasing (x in Boys) (mPh[x] + mCh[x]);
      
      % "there were no ties in either subject, or overall"
      constraint all_different(mPh);
      constraint all_different(mCh);
      constraint all_different (x in Boys) (mPh[x] + mCh[x]);
      
      % "no pupil occupied the same place in both subjects"
      constraint forall (x in Boys) (pPh[x] != pCh[x]);
      
      % "C placed higher in Chemistry than Physics"
      constraint pCh[C] < pPh[C];
      
      solve satisfy;
      

      Solution: Charley got 73% in Physics and 75% in Chemistry.

      Here is the complete table:

      Like

  • Unknown's avatar

    Jim Randell 11:58 am on 30 September 2019 Permalink | Reply
    Tags:   

    Teaser 2842: The best policy 

    From The Sunday Times, 12th March 2017 [link] [link]

    George and Martha’s home insurance policy number is a six-figure number consisting of six different digits. George commented that the number was divisible by each of its digits and also by the sum of its digits. Martha then added that, if you deleted the left-hand digit, then you were left with a five-figure number divisible by the sum of its five digits. If you then deleted that number’s left-hand digit, then you were left with a four-figure number divisible by the sum of its four digits, and so on all the way down.

    What is their policy number?

    [teaser2842]

     
    • Jim Randell's avatar

      Jim Randell 11:59 am on 30 September 2019 Permalink | Reply

      Using copy and paste we can easily make the expressions to feed to the [[ SubstitutedExpression() ]] solver from the enigma.py library.

      The following run file executes in 70ms. (Internal run time of the generated program is 132us).

      Run: [ @replit ]

      #! python -m enigma -rr
      
      # suppose the number is: ABCDEF
      
      SubstitutedExpression
      
      --digits="1-9"
      --answer="ABCDEF"
      
      "ABCDEF % A = 0"
      "ABCDEF % B = 0"
      "ABCDEF % C = 0"
      "ABCDEF % D = 0"
      "ABCDEF % E = 0"
      "ABCDEF % F = 0"
      "ABCDEF % (A + B + C + D + E + F) = 0"
      "BCDEF % (B + C + D + E + F) = 0"
      "CDEF % (C + D + E + F) = 0"
      "DEF % (D + E + F) = 0"
      "EF % (E + F) = 0"
      
      --template="ABCDEF"
      

      Solution: The policy number is 384912.


      I also coded up a custom program for this particular problem.

      It runs in 34ms (with an internal run time of 152µs). So the program produced by the [[ SubstitutedExpression ]] solver executes faster than my custom program:

      # permissible digits (0 is disallowed as n % 0 is undefined)
      digits = range(1, 10)
      
      # find <k> digit numbers such that each suffix is divisible by the sum
      # of the digits in that suffix and the number is divisible by each of
      # it's digits individually.
      def solve(k, n=0, s=0, ds=[]):
        # are we done?
        if k == 0:
          # check for divisibility by all the digits individually
          if all(n % d == 0 for d in ds):
            print(n)
        else:
          # add a new digit to the front
          for d in digits:
            if d not in ds:
              ds1 = [d] + ds
              n1 = n + d * 10**len(ds)
              s1 = s + d
              if n1 % s1 == 0:
                # and solve for the remaining digits
                solve(k - 1, n1, s1, ds1)
      
      # we need 6 digit numbers
      solve(6)
      

      We can however use this program to investigate numbers of different lengths, and we find that 6 is the maximum possible length.

      Like

  • Unknown's avatar

    Jim Randell 5:04 pm on 29 September 2019 Permalink | Reply
    Tags:   

    Brainteaser 1721: Prime leaps 

    From The Sunday Times, 10th September 1995 [link]

    The history-cum-maths teacher asked the class to name some years which the knew from history lessons. Johnny named 1066, the Battle of Hastings, and 1939, the outbreak of the Second World War. The teacher then asked him to calculate the difference between the two and Johnny got the correct answer of 873.

    The teacher then asked Johnny if this difference was prime and Johnny answered correctly that it was not because, for example, it was divisible by three.

    The teacher then asked the class to find the longest list of years they could from 0, 1, 2, …, 1999, 2000 so that for any two numbers in the list their difference was not prime.

    Which numbers are in the longest such list?

    This puzzle is included in the book Brainteasers (2002). The puzzle text above is taken from the book.

    [teaser1721]

     
    • Jim Randell's avatar

      Jim Randell 5:05 pm on 29 September 2019 Permalink | Reply

      First, lets treat the list as a sequence of consecutive integers starting at 0. (We’re only interested in differences, so it doesn’t really matter where we start).

      If we consider the set of numbers (0, 4, 8, 12, 16, …) (i.e. the multiples of 4) then we see the difference between any two numbers is also a multiple of 4, and hence not prime. This allows us to select ⌈n / 4⌉ numbers from a sequence of n numbers.

      And this is the best we can manage. Every segment of size 4 has 1 number (and if there is a shorter segment left over from chopping the sequence into fours, then that also has one number).

      To do better we would have to have a segment of size 4 with (at least) two numbers in it.

      We can’t have … 0 _ 2 _ … or … 0 _ _ 3 … as these have a difference of 2 and 3 respectively, so the only possible segment is … 0 1 _ _ ….

      But any numbers that differ by 1 have to be followed by (or preceded by) 7 gaps:

      So the best we could manage is 2 numbers out of every 9, which is worse than 1 out of every 4.

      So presented with a sequence of 2001 numbers the best we can manage is ⌈2001 / 4⌉ = 501 numbers: (0, 4, 8, 12, 16, …, 1992, 1996, 2000).

      Solution: The longest list contains all exact multiples of 4.

      Considered as years (ignoring the fact that there was no year 0), most of the numbers represent leap years, hence the title of the puzzle.

      Like

    • Lise Andreasen's avatar

      Lise Andreasen 12:18 pm on 5 August 2024 Permalink | Reply

      Elegant.

      Like

  • Unknown's avatar

    Jim Randell 6:14 pm on 27 September 2019 Permalink | Reply
    Tags:   

    Teaser 2975: Hollow cube land 

    From The Sunday Times, 29th September 2019 [link] [link]

    I have a large box of toy building bricks. The bricks are all cubes (the same size), and can be pushed together then dismantled.

    I decided to build the largest cube possible by leaving out all the interior bricks. When my hollow cube was finished I had two bricks left over. I put all the bricks back in the box and gave it to my two children. Each in turn was able to use every brick in the box to construct two hollow cubes, again with all interior bricks removed. Their cubes were all different sizes.

    This would not have been possible had the box contained any fewer bricks.

    How many bricks were in the box?

    [teaser2975]

     
    • Jim Randell's avatar

      Jim Randell 6:57 pm on 27 September 2019 Permalink | Reply

      For n ≥ 2 we can calculate the “hollow cube” number as:

      h(n) = n³ − (n − 2)³ = 6(n − 1)² + 2

      We can then check for values where it is possible to make h(n) + 2 from the sum of two smaller h() numbers, in (at least) two different ways.

      This Python 3 program runs in 81ms.

      Run: [ @replit ]

      from enigma import (irange, inf, subsets, printf)
      
      # "hollow cube" numbers (n >= 2)
      h = lambda n: 6 * (n - 1)**2 + 2
      
      # solve the puzzle using formula for h(n)
      def solve():
        d = dict()
        for n in irange(3, inf):
          # calculate h(n)
          x = h(n)
          printf("[h({n}) = {x}]")
          # can x + 2 be made from the sum of 2 smaller h numbers?
          ss = list(s for s in subsets(d.keys(), size=2) if sum(d[k] for k in s) == x + 2)
          # in 2 different ways?
          if len(ss) > 1:
            printf("t={t} [n={n} x={x}, ss={ss}]", t=x + 2)
            return
          # add the number to the list
          d[n] = x
      
      solve()
      

      Solution: There were 3754 bricks in the box.

      The setter was able to build a hollow cube measuring 26 units along each side, using up 3752 of the bricks (leaving 2 unused).

      One child produced cubes measuring 8 and 25 units along each side, using up 296 + 3458 = 3754 bricks.

      The other child produced cubes measuring 16 and 21 units along each side, using up 1352 + 2402 = 3754 bricks.


      Analytically:

      We are looking for numbers p, q such that:

      6(n − 1)² + 4 = 6(p − 1)² + 2 + 6(q − 1)² + 2
      (n − 1)² = (p − 1)² + (q − 1)²

      So we can look for Pythagorean triples that share a hypotenuse. The smallest is:

      25² = 7² + 24² = 15² + 20²

      from which we see the setter’s cube measured 26 units, and the children’s were (8, 25) units and (16, 21) units.

      For more than 2 children the smallest solution is with 25354 bricks. The setter built a cube measuring 66 units, and there can be up to 4 children with cubes measuring (17, 64), (26, 61), (34, 57), (40, 53) units. Corresponding to:

      65² = 16² + 63² = 25² + 60² = 33² + 56² = 39² + 52²

      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