Tagged: by: Peter Good Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 6:37 pm on 27 August 2021 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 3075: Prime cuts for dinner 

    From The Sunday Times, 29th August 2021 [link] [link]

    Tickets to the club dinner were sequentially numbered 1, 2, …, etc. and every ticket was sold. The number of guests for dinner was the highest common factor of three different two-figure numbers and the lowest common multiple of three different two-figure numbers. There were several dinner tables, each with the same number of seats, couples being seated with friends. The guests on each table added their ticket numbers together and obtained one of two prime numbers, both less than 150, but if I told you the larger prime number you would not be able to determine the other.

    What was the larger of the two prime numbers?

    [teaser3075]

     
    • Jim Randell's avatar

      Jim Randell 7:03 pm on 27 August 2021 Permalink | Reply

      This Python program looks for candidate solutions, but doesn’t show that the tickets can be assigned to tables in the required fashion. However there is only one possible answer, so this is not necessary. (However, it is possible to assign tickets in both cases – see [link]).

      It runs in 234ms.

      Run: [ @replit ]

      from enigma import mgcd, mlcm, subsets, irange, intersect, divisors_pairs, tri, Primes, express, filter_unique, unpack, printf
      
      # generate candidate solutions
      def generate():
      
        # primes less than 150
        primes = Primes(150)
      
        # look for gcds and lcms of 3 2-digit numbers
        (gcds, lcms) = (set(), set())
        for ns in subsets(irange(10, 99), size=3):
          gcds.add(mgcd(*ns))
          lcms.add(mlcm(*ns))
      
        # consider number of tickets, n
        for n in intersect([gcds, lcms]):
          # total sum of tickets
          t = tri(n)
          # consider k tables, with q people per table
          for (k, q) in divisors_pairs(n, every=1):
            if k < 3 or q < 3: continue
      
            # consider 2 primes, for the ticket sums
            for (p1, p2) in subsets(primes, size=2):
              # express the total using 2 of the primes
              for (q1, q2) in express(t, (p1, p2), min_q=1):
                if q1 + q2 == k:
                  yield (n, t, k, q, p1, p2, q1, q2)
      
      # look for candidate solutions, where p1 is ambiguous by p2
      ss = filter_unique(
        generate(),
        unpack(lambda n, t, k, q, p1, p2, q1, q2: p2),
        unpack(lambda n, t, k, q, p1, p2, q1, q2: p1),
      )
      
      for (n, t, k, q, p1, p2, q1, q2) in ss.non_unique:
        printf("n={n}: t={t}; {k} tables of {q} people; ({p1}, {p2}) -> ({q1}, {q2})")
      

      Solution: The larger of the two primes was 109.


      There are 30 tickets:

      gcd(30, 60, 90) = 30
      lcm(10, 15, 30) = 30

      And 30 is the only number that satisfies the conditions.

      So the sum of the ticket numbers is T(30) = 465.

      And the tickets can be arranged into 5 tables of 6 people, to give one of two prime sums for each table as follows:

      Table 1: 2, 3, 4, 5, 7, 8; sum = 29
      Table 2: 1, 9, 13, 27, 29, 30; sum 109
      Table 3: 6, 10, 14, 25, 26, 28; sum = 109
      Table 4: 11, 12, 17, 22, 23, 24; sum = 109
      Table 5: 15, 16, 18, 19, 20, 21; sum = 109

      Table 1: 1, 3, 7, 25, 26, 27; sum = 89
      Table 2: 5, 6, 9, 22, 23, 24; sum 89
      Table 3: 8, 10, 11, 19, 20, 21; sum = 89
      Table 4: 12, 13, 14, 15, 17, 18; sum = 89
      Table 5: 2, 4, 16, 28, 29, 30; sum = 109

      In each case the larger prime is 109.

      And there are many ways to achieve the same sums.

      Like

    • GeoffR's avatar

      GeoffR 9:30 am on 31 August 2021 Permalink | Reply

      I programmed this teaser in two stages, first re-using the few lines of Jim’s code to find the intersection of GCD/LCM values to give the number of guests.

      The next stage was to examine possible table arrangements and arrangements of two prime numbers to make up the sum of tickets.

      I also tested different prime number multipliers e.g 4/1 and 3/2 for the 5 table arrangement and 5/1 and 4/2 for the 6 table arrangement.

      
      from itertools import permutations
      from enigma import mgcd, mlcm, subsets, irange, Primes
       
      # primes less than 150
      primes = Primes(150)
       
      # look for 3 No. 2-digit numbers for gcd and lcm values
      gcds, lcms = set(), set()
      for ns in subsets(irange(10, 99), size=3):
        gcds.add(mgcd(*ns))
        lcms.add(mlcm(*ns))
      
      # Numbers of Guests (N)
      N = list(gcds.intersection(lcms))[0]
      print('No. of guests = ', N)   # N = 30
      
      # Ticket sum of numbers for N guests
      T = N * (N + 1)//2
      print('Sum of all ticket numbers = ', T) 
      
      # 30 people - possible table arrangements:
      # - 5 tables of 6 people or 6 tables of 5 people - two possibilities
      # - 2 tables of 15 people or 15 tables of 2 people - not viable
      # - 3 tables of 10 people or 10 tables of 3 people - not viable
      
      # try 5 tables of 6 people, using 2 primes to make sum of tickets
      # results were found for prime multipliers of 4 and 1 
      # no results from 2 and 3 prime multipliers were found
      print('Two possible prime values:')
      for p1, p2 in permutations(primes, 2):
          if 4 * p1 + p2 == T:
              print( (max(p1, p2), min(p1, p2)),  end = "  ")
      
      # (149, 79)  (109, 89)  (101, 61)  (103, 53)  (107, 37)  (109, 29)  (113, 13)
      # There is only maximum prime i.e. 109, where the other prime could not be known.
      # For maximum primes of 149, 101, 103, 107 and 113, the second prime is known.
      
      # try 6 tables of 5 people, using 2 primes make sum of tickets
      for p3, p4 in permutations(primes,2):
          if 5 * p3 + p4 == T:
              print(max(p3, p4), min(p3, p4))        
      # No solution
      
      # No. of guests =  30
      # Sum of all ticket numbers =  465
      # Two possible prime values:
      # (149, 79)  (109, 89)  (101, 61)  (103, 53)  (107, 37)  (109, 29)  (113, 13)
      
      

      This section of code find the two sets of three two digit numbers used by the setter for the HCF/LCM values in this teaser.

      There were 33 numbers in the GCD set of numbers and 25,608 numbers in the LCM set of numbers, with a minimum value of 30 and a maximum value of 941,094. The setter used the minimum LCM value.

      
      # The number of guests for dinner was the highest common
      # factor of three different two-figure numbers and the 
      # lowest common multiple of three different two-figure numbers.
      
      # Q. What were these two sets of three digit numbers?
      
      from itertools import combinations
      
      from math import gcd, lcm
      for x in combinations(range(10, 100), 3):
        a, b, c = x
        if gcd(a, b, c) == 30:
          print(f"Three 2-digit values for HCF = {a}, {b}, {c}")
      
      for x in combinations(range(10, 100), 3):
        d, e, f = x
        if lcm(d, e, f) == 30:
          print(f"Three 2-digit values for LCM = {d}, {e}, {f}")
      
      # Three 2-digit values for HCF = 30, 60, 90
      # Three 2-digit values for LCM = 10, 15, 30
      # Therefore, a value of 30 was used for number of guests.
      
      

      Like

  • Unknown's avatar

    Jim Randell 4:56 pm on 16 July 2021 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 3069: Fit for purpose 

    From The Sunday Times, 18th July 2021 [link] [link]

    George and Martha bought a new toy for their son Clark. It consisted of a rectangular plastic tray with dimensions 15×16cm and eight plastic rectangles with dimensions 1×2cm, 2×3cm, 3×4cm, 4×5cm, 5×6cm, 6×7cm, 7×8cm and 8×9cm. The rectangles had to be placed inside the tray without any gaps or overlaps. Clark found every possible solution and he noticed that the number of different solutions which could not be rotated or reflected to look like any of the others was the same as his age in years.

    How old was Clark?

    [teaser3069]

     
    • Jim Randell's avatar

      Jim Randell 5:19 pm on 16 July 2021 Permalink | Reply

      I reused the code from rectpack.py, originally written for Enigma 1491, and also used in Teaser 2650.

      Each solution also appears rotated, reflected, and rotated and reflected, so the total number of solutions found is 4× the answer.

      The following Python program runs in 199ms.

      Run: [ @replit ]

      from enigma import (irange, ediv, printf)
      from rectpack import (pack, output_grid)
      
      # width/height of the tray
      (X, Y) = (15, 16)
      
      # rectangles
      rs = list((x, x + 1) for x in irange(1, 8))
      
      # count the solutions
      n = 0
      for (i, s) in enumerate(pack(X, Y, rs), start=1):
        printf("{i}: {s}")
        output_grid(X, Y, s, end="")
        n += 1
      
      printf("age = {x}", x=ediv(n, 4))
      

      Solution: Clark was 10.

      The 10 solutions arise due to the following 2 packings:

      The first has 3 (coloured) sub-rectangles that can be flipped over, giving 2×2×2 = 8 packings.

      The second has only 1 sub-rectangle, so gives 2 packings.

      Like

      • Jim Randell's avatar

        Jim Randell 6:32 pm on 16 July 2021 Permalink | Reply

        And here is an alternate version that calculates a canonical form for each solution, and counts the number of different canonical forms.

        Run: [ @replit ]

        from enigma import (irange, printf)
        from rectpack import (pack, output_grid)
        
        # width/height of the tray
        (X, Y) = (15, 16)
        
        # rectangles
        rs = list((x, x + 1) for x in irange(1, 8))
        
        # rotation / reflection
        rotate = lambda s: tuple(sorted((X - x - w, Y - y - h, w, h) for (x, y, w, h) in s))
        reflect = lambda s: tuple(sorted((X - x - w, y, w, h) for (x, y, w, h) in s))
        
        # canonical form of s
        def canonical(s):
          s = tuple(sorted(s))
          r = rotate(s)
          return min(s, r, reflect(s), reflect(r))
        
        # count the canonical forms
        ss = list()
        for (i, s) in enumerate(pack(X, Y, rs), start=1):
          r = canonical(s)
          if r not in ss:
            ss.append(r)    
            printf("{i} -> {x}", x=len(ss))
            output_grid(X, Y, s)
          else:
            printf("{i} -> {x}", x=ss.index(r) + 1)
          printf()
        
        printf("age = {x}", x=len(ss))
        

        Like

    • Frits's avatar

      Frits 12:31 pm on 19 July 2021 Permalink | Reply

      With analysis to place the biggest piece in top left corner.

      This program ran in 181ms.

       
      from itertools import product
      
      (X, Y) = (15, 16)        # width/height of the tray
      M = 9                    # longest side of rectangle
      
      # return grid coordinates (top left, bottom right) where piece w x h will fit
      def grid_coords(grid, w, h):
        res = []
        for i in range(M, X + M):
          for j in range(M, Y + M):
            if grid[i][j] == 0:
              # horizontal and vertical
              for k in range(2):
                if all(grid[x][y] == 0 for x in range(i, i + h)
                                       for y in range(j, j + w)):
                 res.append([(i - M, j - M), (i - M + h - 1, j - M + w - 1)])
      
                (w, h) = (h, w)   # mirror
        return res       
      
      # print grid without borders   
      def grid_print(grid):
        for i, g in enumerate(grid):
          if M <= i < Y + M - 1:
            print(f"{g[M:-M]}")   
        print()   
      
      # fit k pieces into empty spots in the grid   
      def fit(r, k, s):
        if k == 1:
          # check if last piece fits
          coords = grid_coords(s, r[0][0], r[0][1])
          if coords:
            (tl, rb) = (coords[0][0], coords[0][1])
            for (i, j) in product(range(tl[0], rb[0] + 1), range(tl[1], rb[1] + 1)):
              s[i + M][j + M] = k   
            yield [r.copy() for r in s]       # return copy !!
            # backtrack
            for (i, j) in product(range(tl[0], rb[0] + 1), range(tl[1], rb[1] + 1)):
              s[i + M][j + M] = 0
        else:
          (w, h) = r[0]   # pick first remaining piece from list
          for tl, rb in grid_coords(s, w, h):
            if k == N:
              # only allow the biggest piece 9x8 mostly in the top left quadrant
              # in order to prevent rotated or reflected versions
              #
              # if biggest piece is not in the top left corner (not touching (0, 0)):
              # - if biggest piece lies vertical then placing the 8x7 piece
              #   results in a 9x1 stroke --> impossible
              # - if biggest piece lies horizontal there is a stroke 8xa to the left
              #   and a stroke 8xb to the left (where a + b = 7)
              #   strokes of 8x1, 8x2 or 8x3 are impossible to fill --> impossible
            
              if tl != (0, 0): continue
           
            # update piece in the grid s
            for (i, j) in product(range(tl[0], rb[0] + 1), range(tl[1], rb[1] + 1)):
              s[i + M][j + M] = k   
          
            yield from fit(r[1:], k - 1, s)  
            # backtrack
            for (i, j) in product(range(tl[0], rb[0] + 1), range(tl[1], rb[1] + 1)):
              s[i + M][j + M] = 0
             
           
      # rectangles (biggest first)
      rs = list((x, x + 1) for x in range(8, 0, -1))
      N = len(rs)
      
      # initialize grid with borders of size M
      grid = [[9 for i in range(Y + 2 * M)] for j in range(X + 2 * M)]
      # initialize inner grid to 0
      for i in range(X):
        for j in range(Y):
          grid[i + M][j + M] = 0
             
      # generate solutions
      sols = list(fit(rs, N, grid))   
      
      print("Clark was", len(sols), "years old. \n\nexample:\n")
      grid_print(sols[0])
      

      Like

  • Unknown's avatar

    Jim Randell 3:43 pm on 30 April 2021 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 3058: Total resistance 

    From The Sunday Times, 2nd May 2021 [link] [link]

    A physics teacher taught the class that resistors connected in series have a total resistance that is the sum of their resistances while resistors connected in parallel have a total resistance that is the reciprocal of the sum of their reciprocal resistances, as shown in the diagrams. Each pupil was told to take five 35-ohm resistors and combine all five into a network [using a combination of series and/or parallel connections]. Each pupil then had to calculate theoretically and check experimentally the resistance of his or her network. Every network had a different resistance and the number of different resistances was the maximum possible. The total sum of these resistances was a whole number.

    How many pupils were there in the class and what was the sum of the resistances?

    [teaser3058]

     
    • Jim Randell's avatar

      Jim Randell 4:13 pm on 30 April 2021 Permalink | Reply

      We can make a recursive function to calculate the set of resistances for a collection of k resistors, combined into a circuit using only series and parallel connections (and not “bridge”-type circuits).

      Any permissible circuit is constructed from the connection of two smaller circuits (i.e. circuits using fewer resistors) either in series or in parallel. And we don’t need to keep track of the layout of the smaller circuits, only their resistance values. (Which neatly eliminates the need to remove duplicate circuits). And we can cache these values to avoid recomputing them repeatedly.

      This Python program collects the resistance values of smaller circuits (starting with a single resistor) and combines them to calculate the resistance values of larger circuits. (A unit resistance value is used, which can be multiplied up for circuits consisting of resistors of the same value). It runs in 50ms.

      Run: [ @replit ]

      from enigma import (Rational, irange, cproduct, cached, arg, printf)
      
      Q = Rational()  # implementation of rationals
      
      # series and parallel combinations
      S = lambda x, y: x + y
      P = lambda x, y: Q(1, Q(1, x) + Q(1, y)) # = Q(x * y, x + y)
      
      # generate arrangements of k unit resistors
      @cached
      def arrange(k):
        # if there is only 1 resistor
        if k == 1:
          # there is only 1 arrangement
          return {1}
        else:
          # otherwise split the resistors
          s = set()
          for i in irange(1, k // 2):
            # consider the sub-arrangements
            for (x, y) in cproduct([arrange(i), arrange(k - i)]):
              # and combine them in series and parallel
              s.update({S(x, y), P(x, y)})
          return s
      
      # calculate the different resistances of 5 resistors
      k = arg(5, 0, int)
      R = arg(35, 1, int)
      s = arrange(k)
      printf("[k={k} R={R}] {n} different values; total = {t}", n=len(s), t=sum(s) * R)
      

      Solution: There were 22 pupils in the class. The total sum of the constructed resistance values was 1052 ohms.


      See also: OEIS A048211 [ @oeis ]. I have used my program to verify the sequence up to k = 21, but beyond that requires more memory than my machine has.

      The sequence OEIS A000084 [ @oeis ] gives the total number of different series/parallel circuit configurations that can be constructed, but some of them may have the same resistance value.

      For example the following combinations of 4 resistors give the same value:

      (R + R) | (R + R) = R
      (R | R) + (R | R) = R

      For k = 5 there are 24 different circuits that can be constructed, but only 22 different resistance values.

      The sequence OEIS A337516 [ @oeis ] also includes “bridge”-type circuits (the first of which appears at k = 5) and “fork”-type circuits (which appear at k = 7).

      Like

    • Tony Brooke-Taylor's avatar

      Tony Brooke-Taylor 7:27 pm on 30 April 2021 Permalink | Reply

      Jim, I tried to test my manual solution using your code and can’t reconcile your result for k=3. Have you included cases where there can be 1 resistor in parallel?

      Like

      • Tony Brooke-Taylor's avatar

        Tony Brooke-Taylor 7:43 pm on 30 April 2021 Permalink | Reply

        Sorry, I knew I should have thought a bit harder. Of course I realised my error as soon as I submitted my reply…

        Like

      • Jim Randell's avatar

        Jim Randell 7:53 pm on 30 April 2021 Permalink | Reply

        @Tony:

        With 1 resistor we have 1 way: {R}

        With 2 resistors they can be in series or parallel, 2 ways: {R+R, R|R } = { 2R, (1/2)R }

        With 3 resistors we can combine a group of 1 resistors with a group of two resistors in 4 ways: {R+(R + R), R+(R|R), R|(R + R), R|(R|R) } = { 3R, (2/3)R, (1/3)R, (3/2)R }.

        It is interesting to note that if we can make a resistance of r with a circuit of k unit resistors, then we can also make a resistance of 1/r (by interchanging series and parallel connections).

        Like

    • Alex.T.Sutherland's avatar

      Alex.T.Sutherland 4:57 pm on 2 May 2021 Permalink | Reply

      if bridging is allowed then my answer is 23 pupils and total resistance value = 1087.
      if bridging is not allowed 22 pupils = 1052.
      (the bridge network is 35 ohms)

      Like

      • Jim Randell's avatar

        Jim Randell 5:24 pm on 2 May 2021 Permalink | Reply

        Thanks for your comment.

        I think this puzzle is only concerned with networks that are composed from series and parallel connections (as that is all the children are told about, so they wouldn’t know how to calculate the theoretical resistance of other types of circuits). I have now clarified the puzzle text on this point.

        (I try not to directly reveal the solution to prize puzzles until after it is closed to entries).

        Like

    • Hugh Casement's avatar

      Hugh Casement 1:31 pm on 9 May 2021 Permalink | Reply

      >>
      For k = 5 there are 24 different circuits that can be constructed,
      but only 22 different resistance values.
      <<

      2R and ½R are each duplicated, where R = 35 ohms in this case.

      With four resistors it's just R that's duplicated, as Jim said in his original post on 30 Apr.
      Add an extra resistor to each of those circuits, once in series and once in parallel,
      and we have the duplicates for k = 5.

      Sorry if I'm stating the obvious!

      Like

  • Unknown's avatar

    Jim Randell 9:34 pm on 14 August 2020 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 3021: Field for thought 

    From The Sunday Times, 16th August 2020 [link] [link]

    Farmer Giles had a rectangular field bordered by four fences that was 55 hectares in size. He divided the field into three by planting two hedges, from the mid-point of two fences to two corners of the field. He then planted two more hedges, from the mid-point of two fences to two corners of the field. All four hedges were straight, each starting at a different fence and finishing at a different corner.

    What was the area of the largest field when the four hedges had been planted?

    [teaser3021]

     
    • Jim Randell's avatar

      Jim Randell 10:24 pm on 14 August 2020 Permalink | Reply

      The x and y co-ordinates of the intersections of the hedges helpfully divide the edges of the rectangle into equal divisions.

      The area of the central quadrilateral is then easily calculated.

      Solution: The central field has an area of 11 hectares.

      In the first diagram, each of the four coloured triangular areas has an area of xy/5, so the central region also has an area of xy/5.

      Another way to think of it is that there are five quadrilaterals each identical to the central one, but four of them have had bits sliced off them, and then the sliced off bits have been repositioned to make the original rectangle.

      This gives a handy practical construction achievable using folding and straight edge to divide a rectangle into 5 equal strips (or a 5×5 grid of identical smaller rectangles).


      This is a bit like Routh’s Theorem (see: Enigma 1313Enigma 320Enigma 1076, Teaser 2865) but for a rectangle instead of a triangle.

      In general, if the the lines are drawn from a corner to a point a fraction f along a side we can determine the area of the central quadrilateral (as a fraction of the overall parallelogram) as:

      A = (1 − f)² / (1 + f²)

      In the case of f = 1/2 we get:

      A = (1/2)² / (1 + (1/2)²) = (1/4) / (5/4) = 1/5

      Like

  • Unknown's avatar

    Jim Randell 5:37 pm on 31 January 2020 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 2993: Baker’s weights 

    From The Sunday Times, 2nd February 2020 [link] [link]

    A baker’s apprentice was given a 1kg bag of flour, scales and weights, each engraved with a different whole number of grams. He was told to separately weigh out portions of flour weighing 1g, 2g, 3g, and so on up to a certain weight, by combining weights on one side of the scales. He realised that he couldn’t do this if there were fewer weights, and the largest weight was the maximum possible for this number of weights, so he was surprised to find after one of these weighings that the whole bag had been weighed out. Upon investigation, he discovered that some of the weights weighed 1g more than their engraved weight. If I told you how many of the weights were too heavy, you would be able to work out what they all were.

    What were the actual weights (in ascending order)?

    [teaser2993]

     
    • Jim Randell's avatar

      Jim Randell 8:24 am on 1 February 2020 Permalink | Reply

      When I first read the puzzle it didn’t seem to make any sense, or have a solution.

      So I set about investigating the parts of the text that are unambiguous:

      (a) The apprentice has a set of weights, some of which are mislabelled (weighing 1g more than labelled).

      (b) The apprentice is weighing amounts of 1g, 2g, 3g, … until at some point he unexpectedly has used up exactly 1000g of flour.

      With k weights we can make (2^k − 1) different non-empty collections of weights. Using weights that are powers of 2 (i.e. 1g, 2g, 4g, 8g, …) allows us to weigh all the amounts between 1 and (2^k − 1).

      So we can start weighing out increasing amounts, look at what weights have been used and look at when a collection of mislabelled weights would bring the total amount weighed out to exactly 1000g.

      This Python program runs in 77ms.

      Run: [ @replit ]

      from enigma import (multiset, irange, inf, subsets, nsplit, seq_ordered as ordered, filter_unique, item, printf)
      
      # record possible solutions:
      # (<number of weighings>, <number of mislabelled weights>, <sequence of weights>)
      ss = list()
      
      # record the labels of the weights used
      s = multiset()
      
      # consider possible number of weighings, and total expected amount weighed out
      t = 0
      for n in irange(1, inf):
        t += n
        if t > 1000: break
        # calculate the required weights
        ws = list(2**i for (i, m) in enumerate(reversed(nsplit(n, base=2))) if m)
        printf("{n} -> {t}; {ws}")
      
        # add in the weights
        s.update_from_seq(ws)
        assert t == sum(k * v for (k, v) in s.items())
      
        # now consider a subset of the weights that actually weigh 1g more than labelled
        for xs in subsets(s.keys(), min_size=1):
          # the total extra weight being...
          x = sum(s[x] for x in xs)
          # does this bring the total to exactly 1kg?
          if t + x == 1000:
            k = len(xs)
            printf(" -> {xs}; +{x}; {k}")
            ss.append((n, k, ordered(w + (w in xs) for w in s.keys())))
      
      # find solutions unique by the number of mislabelled weights (= item 1)
      for (n, k, ws) in filter_unique(ss, item(1)).unique:
        # output solutions
        printf("n={n} k={k} ws={ws}")
      

      Solution: The actual weights were: 2g, 3g, 5g, 9g, 17g, 32g.

      So the apprentice has a set of six weights, labelled: 1g, 2g, 4g, 8g, 16g, 32g. Which, if correct, could be used to weigh any integer amount between 1g and 63g.

      However, five of the weights are mislabelled. The 1g, 2g, 4g, 8g, 16g weights all weigh 1g more than their label suggests.

      After the apprentice has weighed out amounts corresponding to 1g, 2g, 3g, …, 42g using the weights he would expect to have used 903g of flour, but with this set of weights he has actually used a total of 1000g of flour.

      The apprentice may have set out to make weights up to 42g (expecting to use 903g of flour), up to 43g (expecting to use 946g of flour), or up to 44g (expecting to use 990g of flour). For higher amounts 1000g of flour would not be enough to complete the task.

      There are also potential solutions when apprentice gets to 43g. With the set of six weights he would expect to have weighed out 946g of flour. But there are four combinations of 3 mislabelled weights, which would bring the total to exactly 1000g. (If the (1, 4, 32), (1, 8, 32), (2, 4, 32) or (2, 8, 32) weights are mislabelled).

      But we are told that if we knew the number of mislabelled weights we could work out the actual weights in the set. So we must be dealing with the case where 5 of the weights are mislabelled.


      The most reasonable scenario seems to be that apprentice was given a 1kg bag of flour and a set of 6 weights, labelled: 1g, 2g, 4g, 8g, 16g, 32g, and asked to weigh out amounts from 1g to 44g.

      The total amount to be weighed out is T(44) = 990g, so he would be expecting to have 10g of flour left at the end.

      However, after one of the weighings he has used up exactly 1000g of flour (assuming the bag of flour was actually 1000g in the first place).

      There 5 ways this can happen:

      After weighing 42g using weights (2, 3, 5, 9, 17, 32) [5 mislabelled weights]
      After weighing 43g using weights (2, 2, 5, 8, 16, 33) [3 mislabelled weights]
      After weighing 43g using weights (2, 2, 4, 9, 16, 33) [3 mislabelled weights]
      After weighing 43g using weights (1, 3, 5, 8, 16, 33) [3 mislabelled weights]
      After weighing 43g using weights (1, 3, 4, 9, 16, 33) [3 mislabelled weights]

      We are told that if we knew the number of mislabelled weights we could work out which they were, so we must be dealing with the first situation with 5 mislabelled weights.

      Like

    • Robert Brown's avatar

      Robert Brown 8:45 pm on 1 February 2020 Permalink | Reply

      He’s told to weigh portions up to a certain weight, must be <=44 as that uses 990g of flour. Binary set of weights goes up to 63g, so some of the weights could be smaller. Text says 'the largest weight was max possible for this number of weights' – I took this to mean there's a weight engraved 32g, but others seem to think it means the largest portion was the max possible for this number of weights. We all get the same answer, but using my method I didn't need to be told how many of the weights were too heavy. Does your program incorporate this?

      Like

      • Jim Randell's avatar

        Jim Randell 8:59 pm on 1 February 2020 Permalink | Reply

        @Robert: I originally thought “the largest weight was the maximum possible for this number of weights” would refer to the largest portion that the apprentice was to weigh out. So it would have to be 31g (with 5 weights) or 63g (with 6 weights), but neither of these can give a solution.

        In the end I assumed that the set of weights used was labelled as powers of 2 (i.e. 1g, 2g, 4g, 8g, …), and then used the program to look for amounts where we would expect (if the weights were correctly labelled) to have weighed out a cumulative amount less than 1000g, but if some of the weights were 1g heavier than labelled the cumulative amount is actually exactly 1000g.

        I found one set with 5 mislabelled weights where this happens, and four sets with 3 mislabelled weights.

        The puzzle text says if we knew the number of mislabelled weights we would know what the actual set of weights was, so the answer we want is the the set with 5 mislabelled weights.

        I think the wording of the puzzle could have been clearer.

        Like

    • Robert Brown's avatar

      Robert Brown 3:49 pm on 3 February 2020 Permalink | Reply

      Jim: I agree with everything that you say, but Brian Gladman seems to think “the largest weight etc” refers to the “certain weight” that the apprentice was told to use as a limit. He then thinks it’s reasonable to set this to 63g. But the person giving instructions to the apprentice would know this was impossible, as even with correct weight labels, the flour would run out after he weighed 44 portions. Of course we don’t know if that person was aware that some of the weights were wrong, which muddies the waters a bit. But Brian’s telling me that I’m effectively solving a different problem, but as far as I can see, it’s the same problem that you have solved.
      In fact, the four sets with 3 mislabelled weights occur at weighing 43, while the the set with 5 mislabelled weights occur at weighing 42. So I discounted weighing 43, which means that I didn’t need to be told the number of mislabelled weights.

      Because the weights we used can give up to 63g, I looked to see what alternatives could give every 1g step up to 44, and found 323 ways to do this, (if the 32g weight is omitted). Beyond my abilities to analyse all of these to see if there’s an alternative solution!

      Like

      • Jim Randell's avatar

        Jim Randell 9:46 am on 4 February 2020 Permalink | Reply

        I think that “the largest weight was the maximum possible for this number of weights” is a roundabout way of saying that that the weights are powers of 2. In a set of 6 (correctly labelled) weights this would mean that the largest weight was 32g, so the remaining 5 weights have to be able to weigh 1g-31g, which means they also have to be powers of 2.

        Using a set of weights that is powers of 2, means that there is only one combination of weights that makes up any specific amount, so when looking for how many times each weight is used in the weighings there is a single answer. Otherwise we may have to consider multiple different ways to make up a specific amount, which could give us different actual weights. So I think this would be a much harder problem (and maybe not have a unique solution).

        If we take “the largest weight was the maximum possible for this number of weights” to mean that the largest amount the apprentice was asked to weigh out was the largest possible for the number of weights, then if the set has 6 weights he would have been asked to weight out amounts up to 63g. This also implies that the set of weights is a “powers of 2” set. But also means that the apprentice was being set an impossible task. (Although there is a long tradition of sending apprentices on futile or impossible tasks, and as it turns out he has been given a doctored set of weights, so his task does indeed turn out to be impossible).

        I think the most reasonable interpretation is that the apprentice was given a set of 6 weights, labelled 1g, 2g, 4g, 8g, 16g, 32g and asked to weigh out amounts up to 42g, 43g or 44g (but we don’t know which). Each of these would appear to be an achievable task.

        As the apprentice weighs out the amounts he finds that the entire bag has been used up after one of the weighings. This is possible in one way after weighing out the 42g portion, and 4 ways after weighing out the 43g portion. We are told that if we knew the number of mislabelled weights, then we could work out which ones they were, so I think we need to take all these cases into account.

        So I think the most reasonable scenario was that the apprentice was asked to weigh out amounts up to 44g, a task which initially looks possible, but depending on the actual set of weights means you would run out of flour after weighing the 42g or 43g portion, making it impossible to complete the task.

        Of the 5 possible sets of weights that lead to exactly 1000g of flour being used before we get to the 44g weight, one of them involves 5 weights being doctored and four of them involved 3 of the weights being doctored. So the answer we want is the set with 5 weights.

        Like

  • Unknown's avatar

    Jim Randell 9:14 am on 7 August 2019 Permalink | Reply
    Tags: by: Peter Good,   

    Teaser 2894: Time duality 

    From The Sunday Times, 11th March 2018 [link] [link]

    After a good breakfast, Seb decided on 40 winks. He noted the time on his digital clock as he dozed off. When he woke up a little later that day, not fully alert, he saw the display reflected in a mirror and was amazed by how long he seemed to have slept. This was in fact 10 times the length of his nap. Next day, a similar thing happened: he fell asleep at the same time and slept a little less, but when he woke, the mirror led him to believe he had slept for 20 times as long as he had. (All times were whole numbers of minutes after midnight).

    At what time did he fall asleep?

    [teaser2894]

     
    • Jim Randell's avatar

      Jim Randell 9:16 am on 7 August 2019 Permalink | Reply

      We can find multiple solutions to this puzzle, depending on how the clock works.

      The program examines the following three scenarios for a digital clock consisting of standard 7-segment digits, where the digits 0, 1 and 8 appear the same when mirrored, and the digits 2 and 5 appear as each other when mirrored.

      Scenario 1: 24 hour clock, always displays 4 digits, reads from 00:00 – 23:59.

      Scenario 2: 24 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 0:00 – 23:59.

      Scenario 3: 12 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 12:00 – 11:59.

      It runs in 125ms.

      Run: [ @replit ]

      from enigma import (defaultdict, cproduct, arg, irange, nsplit, div, sprintf, printf)
      
      # digit reflections
      X = None
      #           0  1  2  3  4  5  6  7  8  9
      reflect = [ 0, 1, 5, X, X, 2, X, X, 8, X ] 
      
      # format time t as hh:mm
      def fmt(t, hours=24):
        k = 0
        while t < 0:
          k -= 1
          t += hours * 60
        while t > hours * 60:
          k += 1
          t -= hours * 60
        (h, m) = divmod(t, 60)
        return sprintf("{h:02d}:{m:02d} [{k:+d}]")
      
      # solve using digits function <digits>
      def solve(digits, hours=24):
        # record results by start time (in minutes), 10x or 20x
        rs = defaultdict(lambda: defaultdict(list))
      
        # map display digits to possible times
        m = defaultdict(list)
        for t in irange(0, 24 * 60 - 1):
          m[digits(t)].append(t)
      
        # find sequences that have a reverse sequence
        for (s, t1s) in m.items():
          r = tuple(reflect[d] for d in s[::-1])    
          if None in r or r == s: continue
          if r in m:
            t2s = m[r]
      
            for (t1, t2) in cproduct([t1s, t2s]):
              if t1 == t2: continue
              while t2 < t1: t2 += 24 * 60
              d = t2 - t1
      
              # find differences that give 9x or 19y
              x = div(d, 9)
              if x:
                t0 = t1 - x
                printf("[{t1} | {t2} = {d} min (9x {x}m), t0={t0}]", t1=fmt(t1, hours), t2=fmt(t2, hours), t0=fmt(t0, hours))
                rs[t0][10].append((t1, t2))
              y = div(d, 19)
              if y:
                t0 = t1 - y
                printf("[{t1} | {t2} = {d} min (19x {y}m), t0={t0}]", t1=fmt(t1, hours), t2=fmt(t2, hours), t0=fmt(t0, hours))
                rs[t0][20].append((t1, t2))
      
        # output solutions
        for (t0, d) in rs.items():
          for ((t1a, t2a), (t1b, t2b)) in cproduct([d[10], d[20]]):
            if t1b < t1a:
              (ft0, ft1a, ft2a, ft1b, ft2b) = (fmt(x, hours) for x in (t0, t1a, t2a, t1b, t2b))
              printf("10x = {ft0} - {ft1a} | {ft2a} / 20x = {ft0} - {ft1b} | {ft2b}")
      
      # digits displayed for time t in the different scenarios:
      
      # [1] four digits, 24 hours: 00:00 - 23:59
      def digits1(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 24, 2) + nsplit(m, 2)
      
      # [2] three or four digits, 24 hours: 0:00 - 23:59, no clear separator
      def digits2(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 24) + nsplit(m, 2)
      
      # [3] three or four digits, 12 hours: 0:00 - 11:59, no clear separator
      def digits3(t):
        (h, m) = divmod(t, 60)
        return nsplit(h % 12 or 12) + nsplit(m, 2)
      
      
      types = {
        '1': [ digits1, "[type 1] 00:00 - 23:59", 24 ],
        '2': [ digits2, "[type 2] 0:00 - 23:59", 24 ],
        '3': [ digits3, "[type 3] 12:00 - 11:59", 12 ],
      }
      
      cmd = arg("123", 0)
      
      for k in sorted(types.keys()):
        if k not in cmd: continue
        (fn, t, h) = types[k]
        printf("{t}")
        solve(fn, hours=h)
        printf()
      

      We find the following solutions:

      Scenario 1: 24 hour clock, always displays 4 digits, reads from 00:00 – 23:59.

      This is probably the most reasonable expectation of the clock’s behaviour without further explanation.

      Day 1: The nap starts at 09:41 and finishes after 74m at 10:55. The mirrored display reads 22:01 corresponding to a nap of 740m (= 10×74m).
      Day 2: The nap starts at 09:41 and finishes after 34m at 10:15. The mirrored display reads 21:01 corresponding to a nap of 680m (= 20×34m).

      Day 1: The nap starts at 09:21 and finishes after 119m at 11:20. The mirrored display reads 05:11 corresponding to a nap of 1190m (= 10×119m).
      Day 2: The nap starts at 09:21 and finishes after 59m at 10:20. The mirrored display reads 05:01 corresponding to a nap of 1180m (= 20×59m).

      But in both these solutions the second nap is less than half the length of the first nap, so it is a bit odd to say he slept “a little less” than the previous day.

      Scenario 2: 24 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 0:00 – 23:59.

      The 09:41 nap works the same, but the 09:21 nap does not as 10:20 when mirrored does not correspond to a displayable time.

      Day 1: The nap starts at 09:41 and finishes after 74m at 10:55. The mirrored display reads 22:01 corresponding to a nap of 740m (= 10×74m).
      Day 2: The nap starts at 09:41 and finishes after 34m at 10:15. The mirrored display reads 21:01 corresponding to a nap of 680m (= 20×34m).

      This scenario has a unique solution, but the problem remains that the second nap is less than half the length of the first nap.

      Scenario 3: 12 hour clock, leading zeros are suppressed on the hours, and no clear hour/minute separator, reads from 12:00 – 11:59.

      Day 1: The nap starts at 07:18 and finishes after 64m at 08:22. The mirrored display reads “558” corresponding to 17:58 and a nap of 640m (= 10×64m).
      Day 2: The nap starts at 07:18 and finished after 57m at 08:15. The mirrored display reads “218” corresponding to 02:18 and a nap of 1140m (= 20×57m).

      And as it is a 12 hour clock this all works shifted on 12 hours, although perhaps 7:18pm is a little late to be having breakfast.

      The problem here is that on day two when seeing the clock reading 2:18 Seb would probably think he had slept for 7 hours, not for 19 hours. However this is the best solution for sleeping “a little less” on the second day, and the puzzle text does say Seb was not fully alert when he read the clock.


      Out of all these scenarios the one that best fits the puzzle text is Scenario 3:

      On the first day, Seb has an early breakfast, and starts his snooze at 7:18am, and wakes up at 8:22am, having slept for 64m, but reads the time as 5:58, and believes he has slept until 5:58pm, which is 640m.

      On the second day, Seb again starts his snooze at 7:18am, and wakes at 8:15am, having slept for 57m (which is only 7m shorter than the previous day). He reads the time as 2:18, and believes he has slept until 2:18am the following day, which is 1140m.

      This gives us a solution to the puzzle that Seb fell asleep on both days at 7:18am.

      It is possible that the phrase “all times were whole numbers of minutes after midnight”, is meant to indicate that all the times mentioned (including the false mirrored times) are all supposed to fall within the same 24 hour day, in which case the 9:41am solution in Scenario 1 or Scenario 2 remain, and give a unique solution of 9:41am. This may be the setters intended solution.

      But as there are multiple possible answers I have marked this puzzle as “flawed“.


      The published solution is: “09:41am”.

      Liked by 1 person

  • Unknown's avatar

    Jim Randell 8:02 am on 5 April 2019 Permalink | Reply
    Tags: by: Peter Good   

    Teaser 2926: Coins of Obscura 

    From The Sunday Times, 21st October 2018 [link] [link]

    George and Martha were on holiday in Obscura where coins are circular with radii equal to their whole number value in scurats. They had coffees and George took out some loose change. He placed one 10 scurat and two 15 scurat coins on the table so that each coin touched the other two and a smaller coin between them that touched all three. He then placed a fifth coin on top of these four which exactly covered them and the total value of the five coins was exactly enough to pay the bill.

    How much was the coffee bill?

    [teaser2926]

     
    • Jim Randell's avatar

      Jim Randell 8:02 am on 5 April 2019 Permalink | Reply

      I think by “exactly covered” the setter means that the fifth coin was the smallest possible circle that would cover the original three coins.

      If you’ve encountered “Soddy Circles” the fourth and fifth coins correspond to the inner and outer Soddy circles formed from the first three coins.

      There is a (relatively) straightforward expression that can be used to calculate the radii of these circles (see: [ Descartes Theorem ]).

      Here is a useful reference for Soddy Circles: [ link ]

      This Python program runs in 89ms.

      Run: [ @replit ]

      from enigma import (is_square, div, printf)
      
      # calculate the radius of the inner and outer Soddy circles
      # (we are only interested in integer solutions)
      def soddy(r1, r2, r3):
        x = r1 * r2 * r3
        y = is_square(x * (r1 + r2 + r3))
        if y is None: return (None, None)
        z = r1 * r2 + r1 * r3 + r2 * r3
        return (div(x, 2 * y + z), div(x, 2 * y - z))
      
      # initial parameters
      (r1, r2, r3) = (10, 15, 15)
      
      # the radii of the Soddy circles
      (r, R) = soddy(r1, r2, r3)
      assert not (r is None or R is None)
      printf("[r1={r1} r2={r2} r3={r3} -> r={r} R={R}]")
      
      # add them all together
      t = r1 + r2 + r3 + r + R
      printf("total = {t}")
      

      Solution: The bill came to 72 scurats.

      The additional coins have values of 2 and 30.

      Here is a diagram. The original coins are shown in black, the inner and outer Soddy Circles (corresponding to the fourth and fifth coins) are shown in red:

      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