Tagged: by: Des MacHale Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 11:09 am on 10 October 2025 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2514: [The Hardy Annular] 

    From The Sunday Times, 28th November 2010 [link] [link]

    The Hardy Annular is an ornamental garden consisting of the area between two circles with the same centre, with the radius of each a whole number of metres. A line joining two points on the circumference of the bigger circle just touches the smaller circle and measures exactly 20 metres.

    What is the radius of each of the circles?

    This puzzle was originally published with no title.

    There are now 1250 Teaser puzzles available on the site (around 38% of all Teaser puzzles published).

    [teaser2514]

     
    • Jim Randell's avatar

      Jim Randell 11:10 am on 10 October 2025 Permalink | Reply

      See also: Puzzle #64.

      We are looking for solutions to the equation:

      R² = r² + 10²

      Here is a solution using the pells.py library (a bit of overkill perhaps for a simple problem, but the code is already written, so here goes):

      from enigma import printf
      import pells
      
      # solve: R^2 - r^2 = 10^2
      for (R, r) in pells.diop_quad(1, -1, 100):
        if R > r > 0:
          printf("R={R} r={r}")
      

      Solution: The circles have radii of 24 m and 26 m.


      Manually, we solve:

      R² − r² = 100
      (R − r)(R + r) = 100

      for positive integer values of R, r.

      So we can consider divisor pairs of 100:

      100 = 1×100 ⇒ R = 50.5, r = 49.5
      100 = 2×50 ⇒ R = 26, r = 24 [SOLUTION]
      100 = 4×25 ⇒ R = 14.5, r = 10.5
      100 = 5×20 ⇒ R = 12.5, r = 7.5
      100 = 10×10 ⇒ R = 10; r = 0

      Only one of the pairs gives positive integer solutions.

      And this is the same process followed by the program.

      Like

    • Ruud's avatar

      Ruud 8:33 am on 11 October 2025 Permalink | Reply

      Strictly speaking the circles could also have a radius of 0 and 10.

      Like

    • Ruud's avatar

      Ruud 8:37 am on 11 October 2025 Permalink | Reply

      for r in range(50):
          for R in range(r, 50):
              if R * R == 100 + r * r:
                  print(r, R)
      

      Like

  • Unknown's avatar

    Jim Randell 9:35 am on 4 March 2025 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2446: [Shuffling cards] 

    From The Sunday Times, 9th August 2009 [link]

    Old Professor Shufflebottom buys a fresh pack of 52 standard playing cards. He has studied various shuffles and knows that, for any shuffle or rearrangement, if he repeatedly performs it, the cards will eventually be returned to their original order. Of the astronomical number of different shuffles possible (1, 2, 3, …, 52), he chooses one requiring the greatest number of repeated shuffles to return the cards to their original order.

    How many times must that shuffle be done before the cards are returned to their original order?

    This puzzle was originally published with no title.

    [teaser2446]

     
    • Jim Randell's avatar

      Jim Randell 9:36 am on 4 March 2025 Permalink | Reply

      By “shuffle” I think we are meant to assume a mathematical permutation of the sequence of 52 cards. (i.e. each time a shuffle is applied to a deck of 52 cards, the top card always ends up in the same position in the shuffled deck, as does the second card, and so on). (See: [ @wikipedia ]

      Maybe it could have read:

      Professor Shufflebottom has devised a machine that shuffles a standard pack of 52 playing cards.

      The machine is configured by setting 52 dials. Each is set with a different number from 1 to 52. The first dial controls the position that the top card in the starting pack will appear in the shuffled pack. The second dial dial controls the position the second card will appear in the shuffled pack, and so on, until all 52 dials are set.

      Professor Shufflebottom sets the dials such that the number of repeated shuffles to return the cards to their original order is as large as possible.

      What is that number of repeated shuffles?


      So the shuffle can be described as a permutation on 52-sequences.

      Any permutation can be broken down into a combination of disjoint cycles, and then the order of the permutation (which is the number of times it needs to be applied for all elements to return to their original positions) is the lowest common multiple of the lengths of the cycles.

      So we need a number of cycles, with a total length of 52, from which we can calculate the order of a permutation consisting of cycles of those lengths. And we are looking for the cycle lengths which give a maximal order.

      The following Python program runs in 631ms (using PyPy).

      from enigma import (Accumulator, irange, decompose, mlcm, arg, printf)
      
      N = arg(52, 0, int)
      printf("[N = {N}]")
      
      # find maximal orders
      r = Accumulator(fn=max, collect=1)
      
      # consider decompositions into 1 .. N tuples
      for k in irange(1, N):
        for ns in decompose(N, k, increasing=1, sep=0, min_v=1):
          # calculate the order
          m = mlcm(*ns)
          r.accumulate_data(m, ns)
      
      printf("max order = {r.value} [from {r.count} decompositions]")
      for ns in r.data:
        printf("  cycles = {ns}")
      

      Solution: The shuffle must be done 180180 times.

      Possible cycle lengths are:

      (3, 4, 5, 7, 9, 11, 13) → sum = 52; lcm = 180180
      (1, 2, 4, 5, 7, 9, 11, 13) → sum = 52; lcm = 180180
      (1, 1, 1, 4, 5, 7, 9, 11, 13) → sum = 52; lcm = 180180

      See also: OEIS A000793.

      Like

      • Jim Randell's avatar

        Jim Randell 9:28 am on 7 March 2025 Permalink | Reply

        Here is a solution that finds the maximal order, without examining all possible decompositions, and allows much larger numbers to be determined.

        It is based on the code given in the OEIS entry, and uses the fact that a maximal decomposition can be constructed that consists of powers of primes, or 1.

        It has an internal runtime of 138µs.

        from enigma import (primes, irange, arg, printf)
        
        N = arg(52, 0, int)
        printf("[N = {N}]")
        
        # compute terms 0 .. n of the landau function
        def landau(n):
          n += 1
          g = [1] * (n + 1)
          for p in primes.between(2, n):
            for j in irange(n, p, step=-1):
              (v, pp) = (g[j], p)
              while pp < j:
                v = max((pp if j == pp else g[j - pp] * pp), v)
                pp *= p
              g[j] = v
          g.pop(0)
          return g
        
        g = landau(N)
        #printf("g[0..{N}] = {g}")
        printf("max order = {r}", r=g[N])
        

        Like

  • Unknown's avatar

    Jim Randell 8:43 am on 17 October 2024 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2603: Pandigital square 

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

    I call my telephone number “pandigital”, in the sense that it is a nine-digit number using each of the digits 1 to 9. Amazingly, it is a perfect square. Furthermore, its square root is a five-digit number consisting of five consecutive digits in some order.

    It might interest you to know (although you do not need to) that my neighbour’s telephone number is also a nine-digit pandigital perfect square, but his is at least double mine.

    With a little logic and not many calculations you should be able to work out my telephone number.

    What is it?

    There are now 1100 Teaser puzzles available on the S2T2 site.

    [teaser2603]

     
    • Jim Randell's avatar

      Jim Randell 8:44 am on 17 October 2024 Permalink | Reply

      Here is a solution using the [[ SubstitutedExpression ]] solver from the enigma.py library.

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

      #! python3 -m enigma -rr
      
      SubstitutedExpression
      
      # consider phone numbers of the form ABCDEFGHI = sq(VWXYZ)
      --distinct="ABCDEFGHI,VWXYZ"
      --invalid="0,ABCDEFGHIV"
      
      # VWXYZ are consecutive digits (in some order) ...
      "is_consecutive(ordered(V, W, X, Y, Z))"
      
      # ... which give a square using each of the digits 1-9 exactly once
      "sq(VWXYZ) = ABCDEFGHI"
      
      --answer="ABCDEFGHI"
      

      Solution: The phone number is 157326849.

      Where:

      sqrt(157326849) = 12543

      There are 24 squares that can be formed from the digits 1-9 (each exactly once) that are at least twice this number.

      The smallest is: 326597184, and the largest is: 923187456.

      So we can suppose that the setter and his neighbour do not share an area code prefix in their phone numbers.


      Manually:

      A number consisting of the digits 1-9 has a digit sum of 45, and so must be divisible by 9, and so its square root must be divisible by 3.

      Using the additional information that the neighbour’s number is at least twice the setter’s number, we can see that the leading digit of the setter’s number must be 1-4, so the 5 digit root is less than 22334, which means it must start with 1 or 2, and so there are only a few possible consecutive digit sets that need to be considered, and only {1, 2, 3, 4, 5} will form numbers divisible by 3.

      So the candidates are: 12xxx, 13xxx, 14xxx, 15xxx, 21xxx. Where each xxx has 6 possibilities, which gives 30 possibilities.

      From these we can eliminate any candidates ending in 51, 52, 53, 235, 243, 245, 345, 423, 435, 532 (as the squares will include 0 or a repeated digit), which brings us down to 16 candidates.

      12 354 → 152621316
      12 534 → 157101156
      12 543 → 157326849 [*SOLUTION*]

      13 254 → 175668516
      13 425 → 180230625
      13 524 → 182898576
      13 542 → 183385764

      14 325 → 205205625
      14 523 → 210917529

      15 234 → 232074756
      15 324 → 234824976
      15 342 → 235376964
      15 432 → 238146624

      21 354 → 455993316
      21 534 → 463713156
      21 543 → 464100849

      And only one of these squares is a reordering of the digits 1-9.

      Like

      • ruudvanderham's avatar

        ruudvanderham 2:59 pm on 17 October 2024 Permalink | Reply

        Enumerating all 5 digit numbers with 5 consecutive numbers and then checking whether the square of that is pandigital:

        from istr import istr
        
        for i in range(1, 6):
            for digit5 in istr.concat(istr.permutations(range(i, i + 5))):
                square_of_digit5 = digit5 * digit5
                if len(square_of_digit5) == 9 and set(square_of_digit5) == set(istr.digits("1-9")):
                    print(digit5, square_of_digit5)
        

        Like

    • GeoffR's avatar

      GeoffR 12:44 pm on 17 October 2024 Permalink | Reply

      As Brian points out on his PuzzlingInPython site for this teaser, the first number is less than 5.10^8 so its square root is less than 22361 and the leading digit is 1 or 2. My neighbour’s telephone number is not needed for the solution.

      
      % 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:I;
      constraint all_different([A,B,C,D,E,F,G,H,I]);
      
      % Telephone number is ABCDEFGHI
      var 100000000..500000000: tel_num == A*pow(10,8) + B*pow(10,7) + C*pow(10,6)
      + D*pow(10,5) + E*pow(10,4) + F*pow(10,3) + G*pow(10,2) + H*10 + I;
      
      % Square root of telephone number is abcde
      var 1..5:a; var 1..5:b; var 1..5:c; var 1..5:d; var 1..5:e;
      constraint all_different([a,b,c,d,e]);
      var 10000..99999: abcde ==  a*pow(10,4) + b*pow(10,3) + c*pow(10,2) + d*10 + e;
      
      constraint a ==1 \/ a == 2;
      constraint abcde * abcde == tel_num;
      
      solve satisfy;
      
      output ["Telephone number = " ++ show(tel_num) ++ "\n"
      ++ "Square root of tel. num. = " ++ show (abcde) ];
      
      % Telephone number = 157326849
      % Square root of tel. num. = 12543
      % ----------
      % ==========
      
      

      Like

    • GeoffR's avatar

      GeoffR 2:11 pm on 17 October 2024 Permalink | Reply

      
      # the first number is less than 5.10^8 so its square root
      # is less than 22361  and the leading digit is 1 or 2 
      # and 5 cconsecutive digits, in some order
      
      from itertools import permutations
      
      for p1 in permutations('12345'):
          a,b,c,d,e = p1
          if a not in ('12'):continue
          abcde = int(a + b + c + d + e)
          tel_num = abcde ** 2
          if tel_num > 5 * 10**8:continue
          if len(set(str(tel_num))) != 9 \
          or len(str(tel_num)) != len(set(str(tel_num))):
              continue
          print('Tel_num =', tel_num)
      
      

      Like

  • Unknown's avatar

    Jim Randell 3:02 pm on 7 May 2024 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2617: A case of ambiguity 

    From The Sunday Times, 18th November 2012 [link] [link]

    Every schoolchild knows that it is possible for two triangles to have two of their lengths-of-sides in common and one of their angles in common without the two triangles being identical or “congruent”.

    This can happen when the common angle is not included between the two common sides. I have found such a pair of non-congruent triangles with all the lengths of the sides being a whole number of centimetres and with the longest side of each triangle being 10cm in length.

    What are the lengths of the other two sides of the smaller triangle?

    [teaser2617]

     
    • Jim Randell's avatar

      Jim Randell 3:02 pm on 7 May 2024 Permalink | Reply

      Each triangle has a longest side of 10, so the remaining two sides must be 1 – 9, so there aren’t that many triangles to consider.

      This Python program considers the side lengths of possible triangles and uses the cosine rule to calculate the internal angles, and then looks for two different triangles that share an angle.

      It runs in 72ms. (Internal runtime is 664µs).

      Run: [ @replit ]

      from enigma import (fraction as Q, irange, intersect, call, cache, printf)
      
      # return values as cosines (using cosine rule)
      cosA = lambda x, y, z: Q(y*y + z*z - x*x, 2*y*z)
      
      # find the angles of a triangle with sides x, y, z
      @cache
      def _angles(x, y, z):
        # is it a valid triangle?
        if x + y > z:
          return {cosA(x, y, z), cosA(y, z, x), cosA(z, x, y)}
      angles = lambda *ss: call(_angles, sorted(ss))
      
      # choose the shared side a
      for a in irange(1, 9):
        # choose the shorter remaining side b
        for b in irange(1, 8):
          angles1 = angles(a, b, 10)
          if not angles1: continue
          # choose the longer remaining side c
          for c in irange(b + 1, 9):
            angles2 = angles(a, c, 10)
            if not angles2 : continue
            # check for a common angle
            if intersect([angles1, angles2]):
              # output solution
              printf("({a}, {b}, 10) -> {angles1}; ({a}, {c}, 10) -> {angles2}")
      

      Solution: The other two sides of the smaller triangle are: 4cm and 8cm.

      The triangles look like this:

      And the common angle α is acos(13/20) ≈ 49.46°.

      Like

    • Frits's avatar

      Frits 5:46 pm on 7 May 2024 Permalink | Reply

      We also have 10^2 – 8^2 = 4 * 9.

      See (here).

      Like

      • Jim Randell's avatar

        Jim Randell 4:41 pm on 8 May 2024 Permalink | Reply

        This result follows directly from using the cosine rule on the shared angle of both triangles:

        Suppose the base of the triangle is d, and we can make two triangles with the same angle α using sides b, a and c, a.

        Then, using the cosine rule on both triangles:

        cos(α) = (d² + b² − a²)/2db = (d² + c² − a²)/2dc

        c(d² + b² − a²) = b(d² + c² − a²)
        (c − b)(d² − a²) − bc(c − b) = 0
        (c − b)(d² − a² − bc) = 0
        [b ≠ c] ⇒
        bc = d² − a² = (d − a)(d + a)

        Which gives a straightforward program:

        from enigma import (irange, divisors_pairs, printf)
        
        d = 10
        for a in irange(1, d - 1):
          for (b, c) in divisors_pairs(d*d - a*a):
            if b < c < d:
              printf("triangles = ({d}, {a}, {b}) ({d}, {a}, {c})")
        

        Like

    • GeoffR's avatar

      GeoffR 6:37 pm on 8 May 2024 Permalink | Reply

      
      % A Solution in MiniZinc
      include "globals.mzn";
      
      var 1..9:A; var 1..9:B; var 1..9:C;
      int: D == 10;  % Two triangles are ABD and ACD
      
      constraint B * C == D * D - A * A;
      constraint B < C /\ C < D;
      
      solve satisfy;
      output ["Two triangles are " ++ show([A,B,D]) ++ " and " ++ show([A,C,D]) ];
      
      % Two triangles are [8, 4, 10] and [8, 9, 10]
      % ----------
      % ==========
      
      

      Like

  • Unknown's avatar

    Jim Randell 11:14 pm on 4 February 2024 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2660: Oblonging 

    From The Sunday Times, 15th September 2013 [link] [link]

    I have made a set of “oblongs”, which is what I call rectangles where the longer sides are one centimetre longer than the shorter sides. I made this set from some A4 sheets of card (without any pasting), cutting out one oblong of each of the sizes 1 cm × 2 cm, 2 cm × 3 cm, 3 cm × 4 cm, and so on up to a particular size. I needed more than one A4 sheet to do this. I have given the set to my family and challenged them to use all the card in jig-saw fashion to make another oblong. After considerable effort they have managed to do this.

    How many oblongs are in the set?

    There are now 1000 Teaser puzzles available on the site.

    [teaser2660]

     
    • Jim Randell's avatar

      Jim Randell 11:15 pm on 4 February 2024 Permalink | Reply

      See also: Enigma 1491.

      An A4 sheet is 21.0 cm × 29.7 cm, so the largest oblong that can be made is 21 × 22.

      And the total area is more than 21 × 29 = 609 sq cm, then we will need multiple A4 sheets to make the oblongs.

      This is sufficient to find a single candidate solution.

      Run: [ @replit ]

      from enigma import (irange, quadratic, printf)
      
      # consider possible oblongs a x (a + 1) and accumulate total area
      t = 0
      for a in irange(1, 21):
        t += a * (a + 1)
        # total area > A4
        if not (t > 609): continue
        # look for an oblong with same area: x(x + 1) = t
        for x in quadratic(1, 1, -t, domain='Z', include='+'):
          printf("1x2 .. {a}x{a1} -> t = {t} -> {x}x{x1}", a1=a + 1, x1=x + 1)
      

      Solution: There are 20 oblongs in the set.

      The oblongs 1×2, 2×3, …, 20×21 have total area of 3080, which is the same as a 55×56 oblong.

      This is the only possible candidate, but it is perhaps more difficult to actually fit the tiles together to make the large oblong.

      However, here is one possible packing:

      Like

  • Unknown's avatar

    Jim Randell 8:37 am on 18 May 2023 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2630: River crossing 

    From The Sunday Times, 17th February 2013 [link] [link]

    Two lads walking together had to get back to their tent which was a short distance south-east of them. However, it involved crossing a river which was running from west to east and was a constant five metres wide. Whichever route they chose, they made sure that they were in the water for the shortest distance possible.

    One lad took the obvious such route and went due south and then due east, but the other took the shortest possible such route, thus cutting his friend’s distance by a quarter.

    What was the length of that shortest route?

    [teaser2630]

     
    • Jim Randell's avatar

      Jim Randell 8:38 am on 18 May 2023 Permalink | Reply

      See also: Teaser 3103.

      They both cross the river at right angles to give a river crossing of 5m.

      We can then remove the river, and the remaining (walking) paths are the sides of a right-angled triangle. The optimal route being the hypotenuse, and the first lad traversing the other two sides.

      So if the triangle has sides (x, y, z), the total length of the first path (including river crossing) is: (x + y + 5) and the total length of the second (optimal) path is (z + 5).

      And so:

      (z + 5) / (x + y + 5) = 3/4
      4z + 5 = 3(x + y)

      In order to get a unique solution to the puzzle we need to assume that the tent is exactly SE of the lads (i.e. on a bearing of 135°).

      Then the first lad travels the same total distance on the south leg of his journey (= x + 5) as he does on the east leg (= y).

      So we have:

      y = x + 5
      z = (3(x + y) − 5)/4 = (3x + 5)/2

      and:

      x² + y² = z²
      x² + (x + 5)² = (3x + 5)²/4
      8x² + 40x + 100 = 9x² + 30x + 25
      x² − 10x − 75 = 0
      (x + 5)(x − 15) = 0
      x = 15, y = 20, z = 25

      So the optimal distance is z + 5 = 30m.

      Solution: The shortest route is 30m.

      And the first lad’s distance is 40m.


      We can solve the quadratic equation using the [[ Polynomial() ]] class from the enigma.py library:

      Run: [ @replit ]

      from enigma import (Polynomial, sq, printf)
      
      # construct the polynomial (quadratic)
      px = Polynomial([0, 1])
      py = px + 5
      pz = (3 * px + 5) * 0.5
      p = sq(px) + sq(py) - sq(pz)
      printf("[p = {p}]")
      
      # find (real, positive) roots
      for x in p.quadratic_roots(domain='F', include='+'):
        (y, z) = (py(x), pz(x))
        printf("x={x:g} y={y:g} z={z:g} -> A={A:g} B={B:g}", A=x + y + 5, B=z + 5)
      

      Or we can solve the problem numerically, using the [[ find_value() ]] solver from the enigma.py library:

      Run: [ @replit ]

      from enigma import (find_value, hypot, fdiv, printf)
      
      # A's distance
      A = lambda x: 2 * (x + 5)
      
      # B's distance
      B = lambda x: hypot(x, x + 5) + 5
      
      # find a value where B/A = 3/4
      f = lambda x: fdiv(B(x), A(x))
      r = find_value(f, 0.75, 0, 1000)
      
      x = r.v
      (a, b) = (A(x), B(x))
      printf("B={b:g} A={a:g} -> B/A={f:g}", f=r.fv)
      

      If we had been told that the total distances travelled were whole numbers of metres, then we could look for appropriate right-angled triangles:

      Run: [ @replit ]

      from enigma import (pythagorean_triples, printf)
      
      for (x, y, z) in pythagorean_triples(995, primitive=0):
        if 4 * z + 5 == 3 * (x + y) and y == x + 5:
          printf("A={A} B={B} [x={x} y={y} z={z}]", A=x + y + 5, B=z + 5)
      

      The triangle we are looking for is a (15, 20, 25) triangle = 5× (3, 4, 5).

      Removing the [[ y == x + 5 ]] condition at line 4 allows us to find further (integer) solutions, where the tent is south and east of the starting position, but not on a bearing of 135°.

      Like

  • Unknown's avatar

    Jim Randell 8:58 am on 1 December 2022 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2689: The right choice 

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

    I am organising a tombola for the fete. From a large sheet of card (identical on both sides) I have cut out a lot of triangles of equal area. All of their angles are whole numbers of degrees and no angle exceeds ninety degrees. I have included all possible triangles with those properties and no two of them are identical. At the tombola entrants will pick a triangle at random and they will win if their triangle has a right-angle. The chances of winning turn out to be one in a certain whole number.

    What is that whole number?

    [teaser2689]

     
    • Jim Randell's avatar

      Jim Randell 8:59 am on 1 December 2022 Permalink | Reply

      Once we have chosen the three angles of the triangle (each an integer between 1° and 90°, that together sum 180°), we can form a triangle with the required area by scaling it appropriately.

      This Python program counts the number of possible triangles and the number of them that are right angled.

      It runs in 53ms. (Internal runtime is 1.0ms).

      Run: [ @replit ]

      from enigma import (decompose, fraction, printf)
      
      # generate possible triangles
      triangles = lambda: decompose(180, 3, increasing=1, sep=0, min_v=1, max_v=90)
      
      # count:
      # t = total number of triangles
      # r = number with a right angle
      r = t = 0
      for (a, b, c) in triangles():
        t += 1
        if c == 90: r += 1
      
      # output solution
      (p, q) = fraction(r, t)
      printf("P(win) = {r}/{t} = {p}/{q}")
      

      Solution: The chance of winning is 1/16.

      There are 720 triangles, and 45 of them are right angled.

      I think it would be annoying to choose a triangle with an 89° angle.

      Like

  • Unknown's avatar

    Jim Randell 10:45 am on 25 August 2022 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2745: Square cut 

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

    Jorkens, the wily old cricketer, is faced with a new type of square cut. His house has three square bedrooms, all of different sizes. He has just bought a new carpet for the largest bedroom and has cut up its old carpet into four rectangular pieces, the smallest of which has an area of four square metres. He is able to use the four pieces to carpet the other two bedrooms exactly.

    What is the area of the largest bedroom?

    [teaser2745]

     
    • Jim Randell's avatar

      Jim Randell 10:46 am on 25 August 2022 Permalink | Reply

      Suppose the floors of the rooms have sides a, b, c (smallest to largest).

      Then, if the carpet from the largest bedroom can be used to exactly carpet the other 2 bedrooms we have:

      c² = a² + b²

      So, (a, b, c) form a right-angled triangle (but this is not necessarily a Pythagorean triple, as we are not told that the sides of the rooms take on integer values).

      Or:

      b² = c² − a²
      ⇒ b² = (c − a)(c + a)

      Each side of the larger square must be reduced (otherwise we have a rectangle with side c that won’t fit in the smaller bedrooms).

      Assuming the carpet is cut into exactly 4 rectangular regions (which may be square), we must have cuts like this:

      (i.e. one cut must go across the entire length of the square, and the rectangles produced from this cut must both have cuts perpendicular to this).

      I supposed we cut off an a × a square for the small room, which leaves three rectangles remaining to assemble into a square for the middle room.

      This gives us 3 remaining pieces of size (for some value d):

      a × (c − a)
      (c − a) × d
      (c − a) × (c − d)

      And in order to be assembled into a square of side b one of the pieces must have a dimension of b.

      So either: b = (c − a) or b = d.

      If b = (c − a) we infer that b = c, which is not possible, so the 3 remaining pieces are:

      a × (c − a)
      (c − a) × b
      (c − a) × (c − b)

      Which fit together like this:

      From which we see (vertical edges):

      b = a + (c − b)
      ⇒ 2b = a + c
      ⇒ b = (a + c) / 2

      i.e. b is the mean of a and c.

      So we write:

      b = a + x
      c = a + 2x

      To give the following diagram:

      From which we see (horizontal edges):

      a + x = 4x
      ⇒ a = 3x

      So:

      a = 3x
      b = 4x
      c = 5x

      (So (a, b, c) is a Pythagorean triple, if we measure it in units of x).

      And the pieces and their areas are:

      a × a = 9x²
      a × (c − a) = 6x²
      b × (c − a) = 8x²
      (c − b) × (c − a) = 2x²

      And the smallest of these (2x²) has an area of 4 square metres hence x² = 2.

      And we want the area of the largest bedroom (c²).

      c² = (5x)²
      ⇒ c² = 25x²
      ⇒ c² = 50 square metres

      Solution: The floor area of the largest bedroom is 50 square metres.


      And we can calculate the floor areas of the other rooms as well:

      small = 18 square metres (a 3√2 metre square)
      middle = 32 square metres (a 4√2 metre square)
      large = 50 square metres (a 5√2 metre square)

      And 18 + 32 = 50.

      The 50 square metre carpet from the largest room is cut into the following rectangles:

      √2 × 2√2 (≈ 1.41 × 2.83) = 4 square metres (b.1)
      2√2 × 3√2 (≈ 2.83 × 4.24) = 12 square metres (b.2)
      2√2 × 4√2 (≈ 2.83 × 5.66) = 16 square metres (b.3)
      3√2 × 3√2 (≈ 4.24 × 4.24) = 18 square metres (a)

      Or with each square having an area of 2 square metres (i.e. of side √2 metres):

      Like

  • Unknown's avatar

    Jim Randell 9:17 am on 13 January 2022 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2850: On course 

    From The Sunday Times, 7th May 2017 [link] [link]

    Hackers-on-Sea golf course is designed by the great Jack Arnold. It is a par-seventy course and its eighteen holes are all par three, four or five. The numbers of all the par-five holes are primes, and the numbers of the par-four holes are odd.

    Recently I only had time to play half the course and ideally my nine consecutive holes should be par thirty-five. However, there is no such collection of holes.

    What are the numbers of the par-four holes?

    [teaser2850]

     
    • Jim Randell's avatar

      Jim Randell 9:17 am on 13 January 2022 Permalink | Reply

      If n3, n4, n5 are the numbers of par 3, 4, 5 holes respectively we have:

      n3 + n4 + n5 = 18
      3 × n3 + 4 × n4 + 5 × n5 = 70

      We can treat the problem as a “money changing” puzzle, i.e. we want to make an amount of 70 using 18 coins of denominations 3, 4, 5.

      The following Python program uses the [[ express() ]] function from the enigma.py library. It runs in 50ms.

      Run: [ @replit ]

      from enigma import (express, primes, irange, subsets, tuples, printf)
      
      # primes up to 18
      primes = set(primes.between(1, 18))
      
      # odd numbers up to 18
      odds = set(irange(1, 18, step=2))
      
      for (n3, n4, n5) in express(70, [3, 4, 5], min_q=1):
        if not (n3 + n4 + n5 == 18): continue
      
        # choose par 5 holes (prime)
        for p5s in subsets(primes, size=n5):
      
          # choose par 4 holes (odd)
          for p4s in subsets(odds.difference(p5s), size=n4):
      
            # the rest are par 3
            par = [3] * 18
            for k in p5s: par[k - 1] = 5
            for k in p4s: par[k - 1] = 4
      
            # no consecutive sequence of 9 holes sums to 35
            if any(sum(t) == 35 for t in tuples(par, 9)): continue
      
            printf("p4s={p4s} p5s={p5s}; {par}")
      

      Solution: The par 4 holes are: 1, 9.

      The par 5 holes are: 2, 3, 5, 7, 11, 13, 17.


      We can use a more sophisticated “money changing” algorithm by using:

      from enigma import Denominations
      ...
      
      for (n3, n4, n5) in Denominations(3, 4, 5).express(70, min_q=1):
        ...
      

      Like

  • Unknown's avatar

    Jim Randell 9:08 am on 29 July 2021 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2806: Jack’s jigsaw 

    From The Sunday Times, 3rd July 2016 [link] [link]

    I made Jack a jigsaw. I started with a rectangle of card that I had cut from an A4 sheet and then I cut the rectangle into pieces. There were some square pieces of sizes (in centimetres) 1×1, 2×2, 3×3, … with the largest having side equal to Jack’s age. The remaining pieces were rectangles of sizes 1×2, 2×3, 3×4, … with the largest length amongst them again being Jack’s age. Then Jack succeeded in putting them together again to form a rectangle, but the perimeter of his rectangle was smaller than the perimeter of my original rectangle.

    What were the lengths of the sides of my original rectangle?

    [teaser2806]

     
    • Jim Randell's avatar

      Jim Randell 9:09 am on 29 July 2021 Permalink | Reply

      The original rectangle is cut from an A4 sheet of card (dimensions = 21.0cm × 29.7cm).

      The maximum square that we can make would be 21cm × 21cm, which puts an upper limit on Jack’s age. However the area of an A4 sheet places a smaller upper limit on Jack’s age, as the sum of the area of the pieces for age 10 would be 715cm² – larger than the area of a single A4 sheet.

      This Python program considers possible ages, and calculates the total area of the rectangular pieces. It then looks for possible dimensions and perimeters for packed rectangles. And looks for two of these that could be the setters and Jack’s rectangles. It then uses the rectpack.py library (see: Enigma 1491, Teaser 2650, Teaser 3069) to attempt to pack the pieces into the required rectangle.

      It runs in 1.94s.

      Run: [ @replit ]

      from enigma import irange, divisors_pairs, cached, printf
      from rectpack import pack_tight, output_grid, by_area
      
      # how to pack a set of rectangles
      pack = lambda x, y, rs: pack_tight(x, y, by_area(rs))
      
      # look for a packing
      @cached
      def check(n, x, y):
        # collect the pieces
        ps = list((k, k) for k in irange(1, n))
        ps += list((k - 1, k) for k in irange(2, n))
      
        # attempt a packing
        printf("[n = {n} -> pack {x} x {y} ...]")
        for s in pack(x, y, ps):
          output_grid(x, y, s)
          return True
        printf("[-> no packing]")
        return False
      
      # total area
      t = 0
      for n in irange(1, 21):
        t += n * (2 * n - 1)
        if t > 624: break
      
        printf("[n={n}; t={t}]")
      
        # find possible dimensions and perimeter for the packed rectangles
        rs = dict(((a, b), 2 * (a + b)) for (a, b) in divisors_pairs(t) if not(n > a))
      
        # consider the setter's rectangle
        for ((a1, b1), p1) in rs.items():
          # it must fit on an A4 sheet
          if a1 > 21 or b1 > 29: continue
      
          # and look for another rectangle, with a smaller perimeter
          for ((a2, b2), p2) in rs.items():
            if not(p2 < p1): continue
      
            # check packing is possible
            if check(n, a1, b1) and check(n, a2, b2):
              # output solution
              printf("n={n}: {a1}x{b1} (p={p1}) -> {a2}x{b2} (p={p2}) [*** SOLUTION ***]")
      

      Solution: The original rectangle measured 12cm × 21cm.

      Here is a diagram of the two packings (12×21 → 14×18):

      There will be many more different packings, as any sub-rectangle consisting of two (or more) pieces can be flipped round. (In fact there are 5156 different packings for the 12×21 rectangle, and 1307 for the 14×18 rectangle).


      The program assumes that the original rectangle was cut parallel to the sides of the A4 sheet, so the smaller side must be no more than 21cm and the longer side no more than 29cm. But rectangles with a dimension larger than these could potentially be made by cutting a rectangle not aligned with the sides. (e.g. We could cut a 7×30 rectangle obliquely from a sheet of A4).

      So there are potentially two possible ages, listed here along with possible rectangles (and perimeters):

      n=7: 7×36 (86), 9×28 (74), 12×21 (66), 14×18 (64)
      n=9: 15×35 (100), 21×25 (92)

      It is not possible to pack the 7×36 or 9×28 rectangles, so there are only 2 viable solutions:

      n=7: 12×21 (66) → 14×18 (64)
      n=9: 15×35 (100) → 21×25 (92)

      In the n=7 case the 12×21 rectangle can easily be cut from an A4 sheet (with a single cut), so this is a viable solution. (Note that as it is possible to cut the 9×28 rectangle from an A4 sheet, we need to show that it cannot be packed in order to rule out multiple solutions).

      In the n=9 case the 15×35 rectangle cannot be cut from an A4 sheet (even obliquely), so this is not a viable solution. (Although the 21×25 rectangle could be cut from an A4 sheet (again with a single cut), the puzzle requires that the rectangle with the larger perimeter be cut out from the A4 sheet).

      Like

      • Frits's avatar

        Frits 2:48 pm on 30 July 2021 Permalink | Reply

        @Jim,

        Checking combination 9 x 28 takes a long time.

        Running time will be under half a second (with CPython) if you add the following to function check (or incorporate it in rectpack.py):

         
        # skip if stacked wide pieces exceed height
        if sum(min(a, b) for a, b in ps if 2 * min(a, b) > x) > y: 
          return False
        

        Like

        • Jim Randell's avatar

          Jim Randell 11:42 am on 31 July 2021 Permalink | Reply

          @Frits: Thanks for the suggestion.

          I’ve added a [[ pack() ]] function to rectpack.py that does a couple of quick checks before starting the packing.

          (And I also added [[ pack_uniq() ]] which generates solutions that are symmetrically distinct, see: Teaser 3069).

          Like

  • Unknown's avatar

    Jim Randell 8:49 am on 14 April 2020 Permalink | Reply
    Tags: by: Des MacHale   

    Teaser 2650: Squares of oblongs 

    From The Sunday Times, 7th July 2013 [link] [link]

    I gave to each of Ruby and Annie a set of “Oblongs”. Each set consisted of nine pieces of card of sizes 1×2, 2×3, 3×4, 4×5, 5×6, 6×7, 7×8, 8×9 and 9×10. The idea was to use some or all of the cards to make various shapes in jigsaw fashion. I asked them to make a square using some of their own pieces. Ruby made the smallest square possible with her set and Annie made the largest square possible with hers. Then I collected up all the unused pieces of card.

    What (in increasing order) were the sizes of these unused pieces?

    [teaser2650]

     
    • Jim Randell's avatar

      Jim Randell 8:49 am on 14 April 2020 Permalink | Reply

      See also: Enigma 10, Enigma 1491, Enigma 1251.

      I packaged up the rectangle packer I wrote for Enigma 1491 into a separate module: rectpack.py.

      This Python program looks for subsets of the tiles that have an area that can be made into a square, and then tries to pack them into the square. It runs in 110ms.

      Run: [ @replit ]

      from rectpack import pack
      from enigma import (irange, subsets, is_square, Accumulator, diff, printf)
      
      # available tiles
      tiles = list((i, i + 1) for i in irange(1, 9))
      
      # find the smallest and largest squares
      rs = [ Accumulator(fn=min), Accumulator(fn=max) ]
      
      # choose subsets of the tiles
      for ts in subsets(tiles, min_size=2):
        # is the area a square number
        t = sum(a * b for (a, b) in ts)
        x = is_square(t)
        if x is None: continue
      
        # attempt to fit the rectangles into the square
        for ps in pack(x, x, ts):
          printf("{t} = {x}^2 -> {ts}")
          printf("-> {ps}")
          for r in rs: r.accumulate_data(x, ts)
          break  # only need one packing
      
      # output solution
      printf("min = {rs[0].value}^2, {rs[0].data}")
      printf("max = {rs[1].value}^2, {rs[1].data}")
      
      # unused tiles
      us = diff(tiles, rs[0].data) + diff(tiles, rs[1].data)
      printf("unused = {us}", us=sorted(us))
      

      Solution: The unused pieces are: 1×2, 2×3, 8×9.

      The smallest square that can be made is a 16×16 square using all the pieces except 1×2 and 8× 9.

      The largest square that can be made is a 18×18 square using all the pieces except 2×3.

      These are in fact the only two sets of pieces that can be assembled into squares.

      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