Teaser 3271: Uncut diamonds
From The Sunday Times, 1st June 2025 [link] [link]
Andrew was building a rhombus-shaped patio. He could have paved it with equilateral triangular slabs with 1ft edges, but he wanted a layout with a hexagonal slab in place of six triangular ones at various places. He considered two layouts that were symmetrical in two perpendicular directions:
Layout 1: every triangular slab touches the perimeter of the patio in at least one point.
Layout 2: each group of three adjacent hexagonal slabs encloses exactly one triangular one.
The triangular and hexagonal slabs come in boxes of 12, and Andrew chose layout 1 because he would only need a third as many boxes of triangular slabs as layout 2.
What length were the sides of the patio and how many slabs in total would be left over?
[teaser3271]










Jim Randell 7:13 am on 1 June 2025 Permalink |
Once you have determined how the two layouts work (isometric graph paper helps), this is a relatively straightforward puzzle.
Here are the two layouts on a rhombus with sides of size 8:
(Layout 1 uses 17 hexes and 26 tris. Layout 2 uses 16 hexes and 32 tris. Note that there are tris in Layout 2 that are not surrounded by 3 hexes).
The following Python program generates increasing sizes for each layout, and determines the (side, hexes, tris) for each case, and then looks for two layouts with the same size where layout 1 requires 1/3 the number of boxes of triangular tiles as layout 2.
It runs in 60ms. (Internal runtime is 266µs).
from enigma import (irange, inf, sq, intersect, divc, printf) # generate (<side>, <hexes>, <tris>) for layout 1 def layout1(M): # consider number of hexagons on the long diagonal for n in irange(1, inf): s = n + 1 if s > M: break h = 2 * sum(irange(n, 1, step=-3)) - n t = 2 * sq(s) - 6 * h yield (s, h, t) # generate (<side>, <hexes>, <tris>) for layout 2 def layout2(M): # there is a sq(n) array of hexagons for n in irange(1, inf): s = 2 * n if s > M: break h = sq(n) t = 2 * sq(s) - 6 * h yield (s, h, t) # collect (h, t) by s for each layout M = 100 (d1, d2) = (dict(), dict()) for (s, h, t) in layout1(M): d1[s] = (h, t) for (s, h, t) in layout2(M): d2[s] = (h, t) # calculate boxes and left overs def boxes(n, k=12): b = divc(n, k) return (b, k * b - n) # examine common side lengths for s in sorted(intersect([d1.keys(), d2.keys()])): ((h1, t1), (h2, t2)) = (d1[s], d2[s]) # check for layout 1 needing 1/3 as many boxes of tris as layout 2 ((b1, r1), (b2, r2)) = (boxes(t1), boxes(t2)) if 3 * b1 == b2: # output solution printf("s={s}: layout 1 = {h1} hex + {t1} tri; layout 2 = {h2} hex + {t2} tri") printf("-> tri: layout 1 = {b1} boxes (rem = {r1}); layout 2 = {b2} boxes (rem = {r2})") ((b1, r1), (b2, r2)) = (boxes(h1), boxes(h2)) printf("-> hex: layout 1 = {b1} boxes (rem = {r1}); layout 2 = {b2} boxes (rem = {r2})") printf()Solution: The sides of the patio were 24 ft. There are 9 slabs left over.
Layout 1 uses 177 hex slabs (= 15 boxes, with 3 unused), and 90 tri slabs (= 8 boxes, with 6 unused).
Layout 2 uses 144 hex slabs (= 12 boxes, with 0 unused), and 288 tri slabs (= 24 boxes, with 0 unused).
LikeLike
Jim Randell 9:45 am on 1 June 2025 Permalink |
Some analysis gives a shorter program:
For a rhombus with side s, the number of hexagons in each of the layouts is:
The following program considers increasing even length sides of the rhombus, until a solution is found.
from enigma import (irange, inf, sq, divc, ediv, printf) # calculate boxes and left overs def boxes(n, k=12): b = divc(n, k) return (b, k * b - n) # consider possible sides of the rhombus for s in irange(2, inf, step=2): n = 2 * sq(s) # number of triangular cells # calculate the number of hex tiles (h1, h2) = (divc(sq(s - 1), 3), sq(ediv(s, 2))) # calculate the number of tri tiles (t1, t2) = (n - 6 * h1, n - 6 * h2) # calculate number of boxes of tri tiles ((b1, r1), (b2, r2)) = (boxes(t1), boxes(t2)) if 3 * b1 == b2: # output solution printf("s={s}: layout 1 = {h1} hex + {t1} tri; layout 2 = {h2} hex + {t2} tri") printf("-> tri: layout 1 = {b1} boxes (rem = {r1}); layout 2 = {b2} boxes (rem = {r2})") ((b1, r1), (b2, r2)) = (boxes(h1), boxes(h2)) printf("-> hex: layout 1 = {b1} boxes (rem = {r1}); layout 2 = {b2} boxes (rem = {r2})") printf() breakLikeLike