Tagged: by: Christopher Higgins Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 10:12 am on 9 April 2023 Permalink | Reply
    Tags: by: Christopher Higgins, ,   

    Teaser 2161: Love hearts 

    From The Sunday Times, 15th February 2004 [link]

    Bobby has made a Valentine’s card for his girlfriend Chin-We. He drew some increasing rows of touching circles, like those shown, but with more rows. Then he put a red heart in as many circles as possible without three of their centres forming an equilateral triangle. Then he put a pink heart in some of the remaining circles, and a white heart in the rest.

    When Bobby counted the number of hearts of red, of pink and of white, he got three totals which (not necessarily in that order) formed three consecutive numbers.

    How many red hearts are on the card?

    Although the puzzle can be solved, the published solution was incorrect, and there are in fact two possible correct answers.

    [teaser2161]

     
    • Jim Randell's avatar

      Jim Randell 10:13 am on 9 April 2023 Permalink | Reply

      I recently revisited Enigma 82 and Enigma 144 and this puzzle can also be solved using similar techniques.

      The number of cells for an arrangement with n rows is obviously tri(n).

      And if the number of red, pink and white hearts are {k − 1, k, k + 1} (in some order), then we can only find a solution when:

      tri(n) = 3k

      And so we can skip cases where tri(n) is not divisible by 3, i.e. n = 4, 7, 10, 13, …

      Once we calculate the possible configurations that give equilateral triangles we can determine a minimum hitting set for these configurations, and all the remaining cells can then be coloured red without giving a configuration that has three reds forming an equilateral triangle, and this is the maximum possible number of reds.

      If this number in in the set {k − 1, k, k + 1} then we have a viable solution, and the cells that form the hitting set can be divided into an appropriate number of pink and white cells.

      This Python program uses the MiniZinc implementation of the minimum hitting set problem and can be used to examine the puzzle for various values of n. The first solution presents itself at n = 11, which the program solves in 3m35s (using the “scip” solver).

      from enigma import (irange, subsets, div, empty, arg, printf)
      from utils_mzn import hitting_set
      
      # distance metric (cosine rule)
      # returns the square of the distance
      def dist(p, q):
        ((px, py), (qx, qy)) = (p, q)
        (a, b) = (abs(px - qx), abs(py - qy))
        c = (1 if (px < qx) != (py < qy) else -1)
        return a * a + b * b - a * b * c
      
      # specify number of rows
      N = arg(9, 0, int)
      
      # enumerate the cells
      n = N - 1
      vs = set((a, b) for a in irange(0, n) for b in irange(0, n - a))
      
      # find the set of equilateral triangles
      tris = set()
      for (a, b, c) in subsets(vs, size=3):
        # is the triangle equilateral
        if dist(a, b) == dist(b, c) == dist(a, c):
          tris.add((a, b, c))
      
      T = len(vs)
      t = len(tris)
      x = div(T, 3)
      ss = ({x - 1, x, x + 1} if x is not None else empty)
      printf("[N={N} -> {T} cells, {t} equilateral triangles, sequence = {ss}]", ss=sorted(ss))
      
      # find a minimum hitting set for the equilateral triangles
      hs = hitting_set(tris, solver="minizinc --solver scip")
      printf("minimum hitting set size = {n}", n=len(hs))
      
      r = T - len(hs)  # max number of red hearts
      printf("maximum red hearts = {r}")
      printf("*** {x}SOLUTION ***", x=('' if r in ss else 'NOT A '))
      

      Solution: The smallest solution has 22 red hearts (with 11 rows of circles), but 25 red hearts is also possible (with 12 rows of circles).

      t = tris; r = reds
       n     t    seq        r  [scip  ] [highs ]
       2     1    0,1,2      2           [ 188ms] [SOLUTION]
       3     5    1,2,3      4           [ 194ms]
       4    15    -          6           [ 188ms]
       5    35    4,5,6      8           [ 206ms]
       6    70    6,7,8     10           [ 242ms]
       7   126    -         12  [ 481ms] [ 449ms]
       8   210    11,12,13  14  [ 1.41s] [  1.5s]
       9   330    14,15,16  17  [ 4.77s] [  7.6s]
      10   495    -         20  [ 14.0s] [ 37.5s]
      11   715    21,22,23  22  [ 3m02s] [13m14s] [SOLUTION]
      12  1001    25,26,27  25  [28m29s] [ 2h15m] [SOLUTION]
      13  1365    -         28  [ 8h18m] [35h21m]
      14  1820    34,35,36  31
      

      t = OEIS A000332
      r = OEIS A240114

      The numbers in seq appear to be growing more rapidly than the numbers in r, so it seems likely these are the only solutions.

      The solution at n = 2 is disallowed as the puzzle text implies that n > 3 (and also as it requires one of the colours to have no corresponding cells).

      Here are some example maximal layouts for various n values:


      The published solution is that there were 16 red hearts.

      And so the numbers of red, pink, white hearts must be 14, 15, 16 to make a total of 45 cells, hence the arrangement has 9 rows.

      However, as we have seen above, the maximum number red hearts for an arrangement with 9 rows is actually 17, so we do not get a solution at n = 9.

      It is possible that the setter(s) assumed that the “inverted-V” shape that we see in solutions for n = 4, 5, 6, which gives a solution with 2(n − 1) red cells, would provide a maximal solution for larger n.

      Like

      • Frits's avatar

        Frits 8:49 pm on 15 April 2023 Permalink | Reply

        @Jim,

        I had a look at [ http://www.hakank.org/minizinc/hitting_set.mzn ] and tried the N=11 case in the MiniZinc program.

        Your model ran for 10 min 52 secs:

        solve minimize(sum(x));
        ....
        constraint x[52] + x[54] + x[61] > 0;
        constraint x[9] + x[21] + x[29] > 0;
        ....
        constraint x[2] + x[9] + x[58] > 0;
        

        The model with predicate hitting_set ran for 6 min 20 secs:

        solve :: int_search(x, most_constrained, indomain_min, complete) minimize k;
        ....
        
        n = 715;
        v = [
        {52, 61, 54},
        {9, 29, 21},
        ....
        {9, 2, 58}
        ];
        

        I guess it’s the “exists” statement in the predicate hitting_set that makes the difference.

        Like

        • Jim Randell's avatar

          Jim Randell 12:04 pm on 16 April 2023 Permalink | Reply

          @Frits: Thanks for the link. I did some tests (with MiniZinc 2.7.2), but found that in general my original formulation ran slightly faster than hakank’s model.

          However, I did download the “scip” solver, and found that it was able to solve the N=11 case in 3m15s, and the N=12 case in just 29m.

          Like

      • Jim Randell's avatar

        Jim Randell 11:58 am on 5 May 2023 Permalink | Reply

        It is possible to install commercial solvers that integrate with MiniZinc and are able to use multiple CPUs.

        The CPLEX solver can be installed from IBM (registration required), and this enables the cplex solver in MiniZinc (you may need to tell it where CPLEX is using the --cplex-dll parameter). You can then use the --parallel <n> parameter to enable multithreading.

        The free version of CPLEX is limited to models with 1000 variables/constraints, but this is sufficient for this problem up to N = 11, which is where the first solution is found. I found CPLEX could solve this using 4 threads in an elapsed time of 42.6s.

        Installing the gurobipy package via pip provides a license to use the Gurobi solver for models with up to 2000 variables/constraints. This is a bit trickier as the free version doesn’t integrate directly with MiniZinc, but I wrote a utils_gurobi.py module to provide the same interface via gurobipy.

        It solves (using 8 threads) the N = 11 case in 22.5s, and the N = 12 case in 9m07s, and the N = 13 case in 2h41m. And it should be able to do the N = 14 case.

        The Gurobi solver uses more CPU time than the (single-threaded) SCIP solver, but because it is able to use multiple CPUs the elapsed time is shorter.

        Like

        • Jim Randell's avatar

          Jim Randell 2:09 pm on 12 May 2023 Permalink | Reply

          Update: I ran the N = 14 case using the Gurobi solver. It took >161 hours (elapsed time), and used >750 hours total CPU time, a lot of RAM, and basically tied up my machine for a week.

          The size of the minimum hitting set is 74, which means the maximum number of red hearts is 31.

          The configuration found looks like this:

          Like

        • Frits's avatar

          Frits 4:57 pm on 12 May 2023 Permalink | Reply

          @Jim, are you going to publish utils_gurobi.py?

          Like

    • Frits's avatar

      Frits 2:14 pm on 13 May 2023 Permalink | Reply

      Or calling print_triangle(hs) for a graphical representation.

         
      def print_triangle(s):
        # from top to bottom
        for r in range(N - 1, -1, -1):
          # in row r only (N - r) elements may be printed
          print(((r // 2) * "  " + (" " if r % 2 else "")), end=" ")
          for c in range(N - r):
            print("." if (r, c) in s else "R", end=" ")  
          print() 
      

      Like

  • Unknown's avatar

    Jim Randell 5:45 pm on 2 November 2021 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Brainteaser 1816: Polls apart 

    From The Sunday Times, 6th July 1997 [link]

    A TV station has commissioned a survey of a small sample of its viewers. One quarter said they watched boxing, one third said they watched tennis, and one half said they watched football. All watched at least one sport. When analysed, the results showed that the number of those questioned who watched just one of the sports equalled the square of the number watching all three. The TV people were unconvinced and asked for a second poll with the number of people questioned increased by 50%. Surprisingly, all that was said above about the first poll was still true for the second.

    How many people were questioned in the first poll?

    [teaser1816]

     
    • Jim Randell's avatar

      Jim Randell 5:46 pm on 2 November 2021 Permalink | Reply

      See also: Brain-Teaser 25.

      If the total number of participants is N, and the 7 regions of the Venn Diagram are: B, T, F, BT, BF, TF, BTF, then we have:

      N = B + T + F + BT + BF + TF + BTF
      N/4 = B + BT + BF + BTF
      N/3 = T + BT + TF + BTF
      N/2 = F + BF + TF + BTF
      B + T + F = BTF²

      Summing the middle three, and then replacing (B + T + F) using the last equation:

      (13/12)N = (B + T + F) + 2(BT + BF + TF) + 3BTF
      (13/12)N = BTF² + 2(BT + BF + TF) + 3BTF
      ⇒ 2(BT + BF + TF) = (13/12)N − 3BTF − BTF²

      And from the first equation:

      (BT + BF + TF) = N − (B + T + F) − BTF
      ⇒ (BT + BF + TF) = N − BTF − BTF²

      equating these:

      2N − 2BTF − 2BTF² = (13/12)N − 3BTF − BTF²
      (11/12)N = BTF² − BTF
      ⇒ N = (12/11)BTF(BTF − 1)

      So for a given value of BTF we can calculate the corresponding value for N.

      This Python program considers increasing (BTF, N) values, and looks for an example viable arrangement by calculating values for the remaining areas of the Venn diagram. When it finds an N value that is 50% more than a previously determined value it stops.

      It runs in 54ms.

      Run: [ @replit ]

      from enigma import (irange, inf, div, decompose, sq, Matrix, as_int, printf)
      
      # generate viable configurations
      def solve():
        # consider values for the number that watch all 3 sports
        for BTF in irange(2, inf):
          # calculate N
          N = div(12 * BTF * (BTF - 1), 11)
          if N is None: continue
          BTF2 = sq(BTF)
          if BTF + BTF2 > N: continue
          
          # choose values for BT, BF, TF
          for (BT, BF, TF) in decompose(N - BTF - BTF2, 3, increasing=0, sep=0, min_v=0):
      
            # determine the remaining variables
            eqs = [
              # B  T  F BT BF TF BTF = k
              ((1, 1, 1, 1, 1, 1, 1), N), # B + T + F + BT + BF + TF + BTF = N
              ((4, 0, 0, 4, 4, 0, 4), N), # B + BT + BF + BTF = N/4
              ((0, 3, 0, 3, 0, 3, 3), N), # T + BT + TF + BTF = N/3
              ((0, 0, 2, 0, 2, 2, 2), N), # F + BF + TF + BFT = N/2
              ((1, 1, 1, 0, 0, 0, 0), BTF2), # B + T + F = BTF^2
              ((0, 0, 0, 0, 0, 0, 1), BTF), # BTF
              ((0, 0, 0, 1, 0, 0, 0), BT), # BT
              ((0, 0, 0, 0, 1, 0, 0), BF), # BF
              ((0, 0, 0, 0, 0, 1, 0), TF), # TF
            ]
      
            try:
              (B, T, F, BT, BF, TF, BTF) = Matrix.linear(eqs, valid=(lambda x: as_int(x, "0+")))
            except ValueError:
              continue
      
            yield (N, B, T, F, BT, BF, TF, BTF)
            break # only need one example for any N
      
      # record results by N
      seen = set()
      for (N, B, T, F, BT, BF, TF, BTF) in solve():
        N_ = 2 * N // 3
        printf("N={N}; B={B} T={T} F={F} BT={BT} BF={BF} TF={TF} BTF={BTF} [(2/3)N={N_}]")
        if N_ in seen: break
        seen.add(N)
      

      Solution: The number of participants in the first poll was 2160.

      And there were 3240 in the second poll.

      Here are example arrangements:

      N=2160; B=495 T=585 F= 945 BT=0 BF=0 TF= 90 BTF=45
      N=3240; B=755 T=865 F=1405 BT=0 BF=0 TF=160 BTF=55

      (There are many possibilities for (BT, BF, TF), but for each (N, BTF) pair they sum to the same value).


      There are many possible arrangements that satisfy the conditions, but there are fewer that have an N value that is 1.5× a smaller N value.

      The program stops when it finds the first solution, but there are further solutions, although they don’t really qualify as “a small sample”:

      N=211680; B=52479 T=53361 F=88641 BT=0 BF=0 TF=16758 BTF=441
      N=317520; B=78840 T=79920 F=132840 BT=0 BF=0 TF=25380 BTF=540

      N=2032553520; B=508095215 T=508181545 F=846940465 BT=0 BF=0 TF=169293130 BTF=43165
      N=3048830280; B=762154704 T=762260436 F=1270398816 BT=0 BF=0 TF=253963458 BTF=52866

      N=199169502480; B=49791948335 T=49792802905 F=82987719985 BT=0 BF=0 TF=16596603970 BTF=427285
      N=298754253720; B=74688040115 T=74689086745 F=124481462365 BT=0 BF=0 TF=24895141180 BTF=523315

      Like

    • Hugh Casement's avatar

      Hugh Casement 6:30 pm on 2 November 2021 Permalink | Reply

      BTF must be a multiple of 11, or 1 more than that, for N to be an integer.

      For any BTF, N pair there are many possible values for BT, BF, and TF.
      But the sum of those three is determined, as shown in the third grey block of Jim’s analysis,
      and it also equals N/12 – 2BTF.

      It turns out to be negative is BTF is too small.

      Like

    • GeoffR's avatar

      GeoffR 8:02 pm on 2 November 2021 Permalink | Reply

      It is easy just to use Jim’s five basic equations in a MiniZinc solution as constraints, although fixing the ranges of variables was not easy to pre-determine.

      The programme took under 2 sec to find the answer, but nearly 2 minutes to exhaust all the subsequent searching with the Chuffed Solver.

      % A Solution in MiniZinc
      include "globals.mzn";
      % re-using Jim's basic equations
      % using upper case variables for the first survey
      % ..and lower case variables for the second survey
      
      var 1..1000:B; var 1..1000:b;
      var 1..1000:T; var 1..1000:t;
      var 1..2000:F; var 1..2000:f;
      var 0..500:BT; var 0..500:bt;
      var 0..500:BF; var 0..500:bf;
      var 0..1000:BTF; var 0..1000:btf;
      var 0..500:TF; var 0..500:tf;
      var 3..5000:N; var 3..5000:n;
      
      % First Survey - main equations
      constraint N == B + T + F + BT + BF + TF + BTF;
      constraint N == 4 * (B + BT + BF + BTF);
      constraint N == 3 * (T + BT + TF + BTF);
      constraint N == 2 * (F + BF + TF + BTF);
      constraint B + T + F == BTF * BTF;
      
      % Second Survey
      % For second survey,  people questioned increased by 50%
      constraint 2 * n == 3 * N;
      
      % Second survey - main equations
      constraint n == b + t + f + bt + bf + tf + btf;
      constraint n == 4 * (b + bt + bf + btf);
      constraint n == 3 * (t + bt + tf + btf);
      constraint n == 2 * (f + bf + tf + btf);
      constraint b + t + f == btf * btf;
      
      solve satisfy;
      
      output [ "People questioned in the first poll = " ++ show(N) ];
      
      % People questioned in the first poll = 2160
      % ----------
      % ==========
      
      
      

      Like

  • Unknown's avatar

    Jim Randell 8:37 am on 31 December 2020 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Teaser 1995: Pyramid selling 

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

    At the fruit stall in our local market the trader built a stack of oranges using the contents of some complete boxes, each containing the same number of oranges.

    He first laid out one box of oranges in a rectangle to form the base of a stack. He then added more oranges layer by layer from the contents of the other boxes. Each layer was a rectangle one orange shorter and narrower than the layer beneath it.

    The top layer should have consisted of a single row of oranges but the trader was one orange short of being able to complete the stack.

    How many oranges were there in each box?

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

    This completes the 72 puzzles from the Brainteasers (2002) book.

    In the New Year I will start posting puzzles from the 1980 book The Sunday Times book of Brain Teasers: Book1 (50 hard (very hard) master problems), compiled by Victor Bryant and Ronald Postill. It is a selection of Teaser puzzles originally published in The Sunday Times between January 1974 and December 1979.

    Happy New Year from S2T2!

    [teaser1995]

     
    • Jim Randell's avatar

      Jim Randell 8:38 am on 31 December 2020 Permalink | Reply

      See: Enigma 1086.

      This Python program runs in 43ms.

      Run: [ @repl.it ]

      from enigma import (irange, inf, div, printf)
      
      # calculate stacking numbers n <= m
      stack = lambda n, m: sum((n - i) * (m - i) for i in irange(n))
      # or: n * (n + 1) * (3 * m - n + 1) // 6
      
      # generate (n, m) pairs where 1 < n < m
      def pairs():
        for t in irange(5, inf):
          for n in irange(2, (t - 1) // 2):
            yield (n, t - n)
      
      # consider n, m values
      for (n, m) in pairs():
        # number of oranges in a box
        b = n * m
        # number of stacked oranges
        s = stack(n, m) - 1
        # number of boxes required
        k = div(s, b)
        if k is not None:
          printf("n={n} m={m} b={b} s={s} k={k}")
          break
      

      Solution: There were 72 oranges in each box.

      3 boxes were used, making a total of 216 oranges.

      The base layer was 6 × 12 layer, using 72 oranges (= 1 box).

      The remaining layers:

      5 × 11 = 55
      4 × 10 = 40
      3 × 9 = 27
      2 × 8 = 16
      1 × 6 = 6 (the final layer is 1 orange short)

      use 55+40+27+16+6 = 144 oranges (= 2 boxes)


      Manually:

      To complete a structure starting with a base that is n × m where n ≤ m, the number of oranges required is:

      S(n, m) = n(n + 1)(3m − n + 1)/6

      And if we use k boxes we have:

      n(n + 1)(3m − n + 1) / 6 = kmn + 1
      n(n + 1)(3m − n + 1) = 6kmn + 6

      n divides the LHS, so n must divide the RHS, hence n divides 6.

      So: n = 1, 2, 3, 6.

      If n = 6:

      m = 12 / (7 − 2k)

      so: m = 12, k = 3.

      If n = 3:

      m = 5 / (6 − 3k)

      doesn’t work.

      If n = 2:

      m = 2 / (3 − 2k)

      doesn’t work.

      If n = 1:

      m = 1 / (1 − k)

      doesn’t work.

      So: n = 6, m = 12, k = 3 is the only viable solution.

      Like

  • Unknown's avatar

    Jim Randell 11:53 am on 3 December 2020 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Teaser 1956: Moving the goalpost 

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

    We have a large rectangular field with a wall around its perimeter and we wanted one corner of the field fenced off. We placed a post in the field and asked the workment to make a straight fence that touched the post and formed a triangle with parts of two sides of the perimeter wall. They were to do this in such a way that the area of the triangle was as small as possible. They worked out the length of fence required (less than 60 metres) and went off to make it.

    Meanwhile, some lads played football in the field and moved the post four metres further from one side of the field and two metres closer to another.

    Luckily when the men returned with the fence it was still the right length to satisfy all the earlier requirements. When they had finished erecting it, the triangle formed had each of its sides equal to a whole number of metres.

    How long was the fence?

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

    [teaser1956]

     
    • Jim Randell's avatar

      Jim Randell 11:54 am on 3 December 2020 Permalink | Reply

      I thought the wording in this puzzle was a bit confusing. Moving the post 4 metres further from one side of the field is necessarily moving it 4 meters closer to another side of the field. I think we are to suppose the sides of the field are those that are used in forming the perimeter of the triangle, but in my code I considered all 8 potential positions.

      If the post is at (a, b), then we can show that the minimal area triangle (made with the x– and y-axes) is achieved when the fence runs from (2a, 0) to (0, 2b). So the post is at the mid-point of the fence.

      The final triangle is a Pythagorean triple with hypotenuse z, less than 60, and, if the hypotenuse passes through the point (a′, b′), then the other sides are, 2a′ and 2b′.

      So we need to look for points (a, b), where a and a′ differ by 2 or 4, and b and b′ differ by 4 or 2, such that (2a)² + (2b)² = z².

      This Python program runs in 46ms.

      Run: [ @replit ]

      from enigma import (pythagorean_triples, cproduct, Rational, printf)
      
      # choose a rational implementation
      Q = Rational()
      
      # consider pythagorean triples for the final triangle
      for (x, y, z) in pythagorean_triples(59):
        # and the position of the post
        (a1, b1) = (Q(x, 2), Q(y, 2))
        # consider the original position of the post
        for ((dx, dy), mx, my) in cproduct([((2, 4), (4, 2)), (1, -1), (1, -1)]):
          (a, b) = (a1 + mx * dx, b1 + my * dy)
          if a > 0 and b > 0 and 4 * (a * a + b * b) == z * z:
            printf("({x}, {y}, {z}) -> (a1, b1) = ({a1}, {b1}), (a, b) = ({a}, {b})")
      

      Solution: The fence is 25m long.

      The triangles are a (7, 24, 25) and a (15, 20, 25) triangle.

      The program finds 2 solutions as we don’t know which is the starting position and which is the final position:

      However, if the post is moved 2m closer to one of the axes and 4m further from the other axis, then blue must be the starting position and red the final position.

      Like

    • John Crabtree's avatar

      John Crabtree 3:30 pm on 4 December 2020 Permalink | Reply

      As shown above, the post is at the midpoint of the fence.
      Let the initial sides be A and B, and the new sides be A + 8 and B – 4.
      One can show that B = 2A + 10, and if the hypotenuse = B + n then A = 2n + sqrt(5n^2 + 20n),
      n = 1 gives A = 7, ie (7, 24, 25) and (15, 20, 25)
      n = 5 gives A = 25, ie (25, 60, 65) and (33, 56, 65)
      This explains the limit on the length of the fence being less than 60 metres
      BTW, n = 16 gives (72, 154, 170) and (80, 150, 170)

      Like

  • Unknown's avatar

    Jim Randell 8:45 am on 30 August 2020 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Teaser 1858: Cash flow 

    From The Sunday Times, 26th April 1998 [link]

    We play a variation of a famous puzzle game using coins instead of rings. We start with a pile of coins consisting of at least one of each of the 1p, 2p, 5p, 10p, 20p, 50p and £1 coins, with no coin on top of another that is smaller in diameter. So the 5p coins are on the top, then the 1p, 20p, £1, 10p, 2p and 50p coins respectively, with the 50p coins being on the bottom. One typical pile is illustrated:

    The object of the game is to move the pile to a new position one coin at a time. At any stage there can be up to three piles (in the original position, the final position, and one other). But in no pile can any coin ever be above another of smaller diameter.

    We did this with a pile of coins recently and we found that the minimum number of moves needed equalled the value of the pile in pence. We then doubled the number of coins by adding some 1p, 5p and 50p coins totalling less than £3, and we repeated the game. Again the minimum number of moves equalled the value of the new pile in pence.

    How many coins were in the pile for the first game?

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

    [teaser1852]

     
    • Jim Randell's avatar

      Jim Randell 8:46 am on 30 August 2020 Permalink | Reply

      (See also: Enigma 1254, Enigma 14).

      In a standard Towers of Hanoi problem there are n discs of different sizes.

      In the optimal solution the largest disc is moved 1 time, the next largest 2 times, then 4 times, 8 times, 16 times, …

      So we get a total number of moves: H(n) = 2^n − 1.

      In this version there are multiple discs the same size, but we can treat a block of k discs the same size as a single disk that requires k moves, and solve the puzzle in the same way.

      So, the stack shown in the diagram (which I denote (1, 2, 1, 1, 3, 1, 1), by counting the number of coins of each size, starting at the bottom), will require: 1×1 + 2×2 + 1×4 + 1×8 + 3×16 + 1×32 + 1×64 = 161 moves.

      In general if there number of coins of each size is (A, B, C, D, E, F, G) then the number of moves is:

      A + 2B + 4C + 8D + 16E + 32F + 64G

      and the monetary value of the coins is:

      50A + 2B + 10C + 100D + 20E + F + 5G

      and if these values are equal, we get:

      49A + 6C + 92D + 4E = 31F + 59G

      In the puzzle, the number of coins is doubled by increasing A by a, F by f, G by g, and their monetary value is less than £3:

      50a + f + 5g < 300

      but the monetary value of the augmented stack is still equal to the number of moves required, so:

      49a = 31f + 59g

      We can work out possible values for a, f, g, and their sum gives us the initial number of coins (which is the answer to the puzzle).

      We can then look for stacks of coins of this size with the monetary value and number of moves, and then add the extra coins to the stack and see if the condition still holds.

      This Python 3 program runs in 54ms.

      Run: [ @replit ]

      from enigma import (irange, div, printf)
      
      # denominations of coins by size (largest diameter to smallest diameter)
      ds = (50, 2, 10, 100, 20, 1, 5)
      
      # number of moves for sequence of discs (largest to smallest)
      def H(ns):
        t = 0
        m = 1
        for n in ns:
          t += m * n
          m *= 2
        return t
      
      # decompose <t> into <k> positive numbers
      def decompose(t, k, s=[]):
        if k == 1:
          yield s + [t]
        else:
          for x in irange(1, t + 1 - k):
            yield from decompose(t - x, k - 1, s + [x])
      
      # choose a value for a (= 50p, so there must be 1-5)
      for a in irange(1, 5):
        # choose a value for g (= 5p)
        for g in irange(1, (299 - 50 * a) // 5):
          # calculate f
          f = div(49 * a - 59 * g, 31)
          if f is None or f < 1 or not(50 * a + 5 * g + f < 300): continue
          # the total number of extra coins = the number of original coins
          n = a + f + g
          # output solution
          printf("n={n} [a={a} f={f} g={g}]")
      
          # allocate the number of original coins (n in total)
          for ns in decompose(n, 7):
            # calculate the total value of the stack
            t = sum(n * d for (n, d) in zip(ns, ds))
            # calculate the number of moves for the stack
            m = H(ns)
            if m != t: continue
      
            # make the final stack
            ns2 = list(ns)
            ns2[0] += a
            ns2[5] += f
            ns2[6] += g
            # calculate the total value of the stack
            t2 = sum(n * d for (n, d) in zip(ns2, ds))
      
            # output solution
            printf("-> {ns} [{t}] -> {ns2} [{t2}]")
      

      Solution: There were 12 coins in the original pile.

      There is only one possible size for the original pile, and it must be composed of: (2× 50p, 1× 2p, 1× 10p, 1× £1, 3× 20p, 1× 1p, 3× 5p), making a total value of 288p and requiring 288 moves.

      We then add: (5× 50p, 6× 1p, 1× 5p) = 261p to make a pile with total value 549p and requiring 549 moves.

      Like

  • Unknown's avatar

    Jim Randell 8:17 am on 17 March 2020 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Brainteaser 1798: Trisection 

    From The Sunday Times, 2nd March 1997 [link]

    We have taken a piece of paper in the shape of an equilateral triangle and folded it so that one of the corners lies at some point on the opposite side:

    In the figure triangle A has an area of 36 cm²  and triangle B has an area of 16 cm².

    What is the area of the unfolded piece of paper?

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

    [teaser1798]

     
    • Jim Randell's avatar

      Jim Randell 8:17 am on 17 March 2020 Permalink | Reply

      (See also: Enigma 1402).

      We note that triangles A and B are similar (they both have angles of (60°, θ, 120° − θ)).

      And their areas are in the ratio 36:16 = 6²:4², so their sides are in the ratio 6:4 = 3:2.

      We can label the sides of A as (3x, 3y, 3z) and of B as (2x, 2y, 2z).

      Looking at the base of the original triangle we see it has a length of: (2x + 3y)

      And so the the missing lengths on the other sides are: (3y − x) and (2x + y)

      But these are also the lengths of the remaining sides of triangles A and B, hence:

      (3y − x) / (2x + y) = 3 / 2
      6y − 2x = 6x + 3y
      3y = 8x

      So triangle A has sides of 3x and 8x, separated by an angle of 60°, and it has an area of 36, so:

      36 = (1/2)(3x)(8x)sin(60°)
      36 = 6x²√3
      x²√3 = 6

      And the base of the original triangle is 8x + 2x = 10x, so the total area is:

      T = (√3/4)(10x)²
      T = 25x²√3
      T = 25×6 = 150

      Hence:

      Solution: The area of the original triangle is 150 cm².

      Like

  • Unknown's avatar

    Jim Randell 8:37 am on 22 December 2019 Permalink | Reply
    Tags: by: Christopher Higgins,   

    Brainteaser 1782: Unwinding 

    From The Sunday Times, 10th November 1996 [link]

    Our Vienna clock will run for about eight days when fully wound, so I wind it up each Sunday morning. But last Sunday this caused a problem as, after I had wound it up, the hands started rotating at many times their normal speed. Thereafter they slowed down at a steady rate until they stopped sometime after 5pm.

    Interestingly, they told the correct time on the hour at each hour between winding up and stopping.

    What was the correct time when the clock stopped?

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

    [teaser1782]

     
    • Jim Randell's avatar

      Jim Randell 8:38 am on 22 December 2019 Permalink | Reply

      The clock undergoes a period when the hands are rotating (rotating at a constant rate) much faster that normal. Then, at some point, they begin to slow (slowing at a constant rate) until the hands stop completely, some time after 5pm.

      Presumably this happens when the hands indicate a time of “about 8 days” (say 180 – 204 hours) from the winding time (which is sometime before 12pm).

      I made some assumptions to simplify the programming:

      Having not heard of a “Vienna clock” I assumed the clock was a normal 12 hour timepiece.

      I assumed the clock was wound up sometime between 11am and 12pm, and set off advancing at many times normal speed, but at some point at or before 12pm started slowing. After that the amount advanced by the clock at 12pm, 1pm, 2pm, 3pm, 4pm, 5pm, was sufficient that the clock showed the correct time. So each one was actually displaying a time exactly some multiple of 12 hours in advance of the actual time. The clock then stopped sometime between 5pm and 6pm (actual time).

      The following Python code examines this situation. It runs in 289ms.

      Run: [ @repl.it ]

      from fractions import Fraction as F
      from enigma import (irange, Polynomial, nsplit, div, sprintf as f)
      
      # format time t as hh:mm:ss.ss
      def hms(t, fmt="{h:d}:{m:02d}:{s:05.2f}"):
        (t, r) = divmod(3600.0 * t, 1)
        (h, m, s) = nsplit(int(t), base=60)
        s += r
        return f(fmt)
      
      # consider number of hours advanced at 12pm
      for h0 in irange(12, 192, step=12):
        # at 1pm
        for h1 in irange(h0 + 1, 193, step=12):
          # at 2pm
          for h2 in irange(h1 + 1, 194, step=12):
            # use the three points to determine the quadratic equation
            # y = a.x^2 + b.x + c
            q = Polynomial.interpolate([(0, h0), (1, h1), (2, h2)])
            if q is None or len(q) < 3: continue
            (c, b, a) = q
      
            # does it achieve a maximum in [5, 6]
            if not(a < 0): continue
            m = F(-b, 2 * a)
            if not (5 < m < 6): continue
      
            # check the times at 3pm, 4pm, 5pm
            hs = [h0, h1, h2]
            for x in (3, 4, 5):
              y = div(q(x), 1)
              if y is not None and y % 12 == x:
                hs.append(y)
            if len(hs) < 6: continue
      
            # find the earliest start time
            s = F(h0, 1 - b)
            if not (-1 < s < 0): continue
      
            # check the total time advanced is in the required range (7.5 - 8.5 days)
            t = q(m) - s
            if not (180 < t < 204): continue
      
            print(f("stop={m} [hs={hs}, start={s}, total={t:.2f}h]", m=hms(m), s=hms(s % 12), t=float(t)))
      

      Solution: The correct time when the clock stopped was 5:35pm.


      We find a solution, with the number of hours advanced from 12pm at (12pm, 1pm, 2pm, 3pm, 4pm, 5pm) as follows:

      (+12, +73, +122, +159, +184, +197)

      The residues mod 12 of each of the values are:

      (0, 1, 2, 3, 4, 5)

      So we see that the clock would show the correct time on each hour.

      The differences between the successive terms of the sequences are:

      (61, 49, 37, 25, 13)

      Each term decreases by 12 from the previous one, so the clock is slowing at a constant rate, and comes to a stop at x = 67/12, which corresponds to 5:35pm.

      The corresponding quadratic equation is:

      y(x) = −6x² + 67x + 12

      At 12pm the clock is advancing at 67× normal speed (y'(0) = 67), so the maximum possible time after winding would be if immediately after winding, the clock set off at a constant 67× normal speed until 12pm, at which point it began to slow down.

      This places the earliest winding time at 11:49:05.5am.

      If the clock starts advancing at 67× normal speed at this time, then in the first 9.8 seconds it advances to show 12:00, and in the remaining 10m44.8s it advances another 12 hours, so that at 12pm (actual time) the clock shows 12:00.

      In the following hours the slowing clock advances an appropriate number of hours to show the correct time on each hour, until it stops at 5:35pm. In the time since winding it has advanced 199.22 hours, approximately 8.3 days, which is in the range we are expecting.

      If the clock started slowing before 12pm than it would be running at faster than 67× normal rate after winding, and the time of the winding would be closer to 12pm. But the total amount the clock has advanced is at least 197 hours (= 8.2 days), so we still get a viable answer.


      However, if it is possible that the clock was running at a constant speed until some time after 12pm, then we can get different answers to the published solution.

      For example, if the number of hours advanced at (12pm, 1pm, 2pm, 3pm, 4pm, 5pm) is:

      (+12, +49, +86, +123, +160, +197)

      The the correct time is displayed at the required times, and each value is 37 hours advanced from the previous value, so the clock is advancing at a constant rate of 37× normal speed. The time the clock was wound up was 11:40:00am.

      At (or after) 5pm the clock can be begin to slow and finally run down at whatever time we choose (between 5pm and 6pm).

      For example, if, at 5pm, the clock slows according to the following equation:

      y(x) = −74x² + 777x − 1838

      Then we have y(5) = 197, y'(5) = 37, y'(5.25) = 0, so y achieves a maximum at y(5.25) = 201.625.

      Which means the clock stops at 5:15pm, having advanced 201.96 hours (= 8.4 days). Which provides a viable alternative solution.

      So we do need to make some additional assumptions in order to arrive at a unique solution. The one I’ve highlighted in bold above is probably the key one.

      Like

      • John Crabtree's avatar

        John Crabtree 1:53 am on 23 December 2019 Permalink | Reply

        From 4.00pm to 5.00pm the clock traveled 13 hours
        From 3.00pm to 4.00pm the clock traveled 25 hours
        From 2.00pm to 3.00pm the clock traveled 37 hours
        From 1.00pm to 2.00pm the clock traveled 49 hours
        From 12.00pm to 1.00pm the clock traveled 61 hours
        That is a little over 7.5 days, and so the clock started some time before 12.00pm, and the rate of decrease is correct.

        Let the relative speed at 4.30pm, ie the average of the speeds at 4.00 and 5.00 pm, be 13.
        Then the relative speed at 3.30pm, ie the average of the speeds at 3.00 and 4.00 pm, is 25.
        The clock stopped an additional 13 / (25 – 12) = 13 / 12 hours after 4.30pm.
        And so the clock stopped at 5.35pm.

        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