Teaser 3176: Equal shares
From The Sunday Times, 6th August 2023 [link] [link]
When I married, my wife insisted that everything be equally shared between us, which I readily agreed to, provided it included the gardening.
The garden is rectangular, with a smaller rectangular vegetable plot, of different relative dimensions, in one corner, the area of which is less than 7 per cent of that of the whole garden. The rest of the garden is lawned.
To satisfy my wife, I constructed the shortest straight length of partition that would split the garden in half, so that half the vegetable plot and half the lawn were each side of the partition. The length of the partition was 30 metres, which exactly equalled the perimeter of the vegetable plot. Both before and after partitioning, all side lengths were an exact number of metres.
What is the area of the lawn in each half?
[teaser3176]










Jim Randell 5:40 pm on 4 August 2023 Permalink |
See also: Puzzle #213.
I am assuming the layout is similar to this previous puzzle, with the vegetable plot fully occupying a corner of the garden.
I used the [[
line_intersect()]] function in the enigma.py library to determine where the partition meets the boundaries of the garden.This Python program runs in 170ms.
Run: [ @replit ]
from enigma import (Rational, irange, subsets, decompose, line_intersect, sq, catch, printf) Q = Rational() h = Q(1, 2) # check for partition crossing L/R boundaries def check1(x, y, a, b): r = line_intersect((h * a, h * b), (h * x, h * y), (0, 0), (0, y), internal=2, div=Q) return r.y.denominator == 1 and sq(x) + sq(y - 2 * r.y) == 900 # check for partition crossing U/D boundaries def check2(x, y, a, b): r = line_intersect((h * a, h * b), (h * x, h * y), (0, 0), (x, 0), internal=2, div=Q) return r.x.denominator == 1 and sq(x - 2 * r.x) + sq(y) == 900 # consider the dimensions of the garden for (y, x) in subsets(irange(1, 50), size=2): # consider dimensions of the vegetable plot for (a, b) in decompose(15, 2, increasing=0, sep=1, min_v=1): if not (a < x and b < y and Q(a, b) not in {Q(x, y), Q(y, x)} and a * b < Q(7, 100) * x * y): continue # look for a solution if any(catch(fn, x, y, a, b) for fn in [check1, check2]): # calculate allocation of lawn lawn = x * y - a * b printf("lawn allocation = {r} m^2 [x={x} y={y}; a={a} b={b}]", r=h * lawn)Solution: Each half has 270 sq m of lawn.
And 18 sq m of vegetable plot.
The garden is a 18 m × 32 m and the vegetable plot is 3 m × 12 m.
LikeLike
Jim Randell 10:53 pm on 4 August 2023 Permalink |
Or here is an alternative approach:
We know the veg plot has a perimeter of 30, and integer sides, so we can generate possibilities for the dimensions. We can then look for an integer distance from a corner for the partition to hit the perimeter, and that gives us a line through the centre of the veg plot, and we can extend that line until it is 30m long, which gives us the overall dimensions of the garden.
This Python program runs in 55ms. (Internal runtime is 332µs).
Run: [ @replit ]
from enigma import (irange, decompose, ihypot, div, printf) # consider the (a, b) veg plot, it has a perimeter of 30 for (a, b) in decompose(15, 2, increasing=0, sep=1, min_v=1): # and where the partition hits the perimeter of the veg plot for d2 in irange(2, a - 1, step=2): # calculate the size of the (x, y) garden h = ihypot(a - d2, b) if h is None: continue x = div(30 * (a - d2), h) y = div(30 * b, h) if x is None or y is None: continue x += d2 # check area and ratio conditions if not (100 * a * b < 7 * x * y): continue if a * y == x * b or a * x == y * b: continue # calculate the allocation of lawn lawn = (x * y - a * b) * 0.5 printf("lawn allocation = {lawn:g} m^2 [a={a} b={b} d={d} -> x={x} y={y}]", d=d2 // 2)LikeLike
Frits 11:23 pm on 4 August 2023 Permalink |
@Jim, I don’t immediately see with this program how you can guarantee with that also the lawn is divided in half.
LikeLike
Jim Randell 11:30 pm on 4 August 2023 Permalink |
@Frits: Because the line that forms the partition passes through both the centre of the the veg plot and the centre of the entire garden, so each is divided exactly in half.
LikeLike
Frits 12:04 am on 5 August 2023 Permalink |
@JIm, Thanks. I now see that the partition passes through the centre of the entire garden because of the adjustment of the x variable.
LikeLike
Frits 10:37 am on 5 August 2023 Permalink |
Similar to the alternative approach.
from enigma import pythagorean_triples, div # (a - 2 * d)^2 + b^2 = h^2, max(a - 2 * d, b) = 12 with d > 0 for (p, q, h) in pythagorean_triples(12): # check both combinations of p and q for (j, k) in [(p, q), (q, p)]: a, b, amin2d = 15 - j, j, k if a < b: continue (d, r) = divmod(a - amin2d, 2) if not r and d > 0: x = div(30 * amin2d, h) y = div(30 * b, h) if x is None or y is None: continue x += 2 * d if not (100 * a * b < 7 * x * y): continue if a * y == x * b or a * x == y * b: continue # calculate the allocation of lawn lawn = (x * y - a * b) / 2 print(f"answer: {lawn:g} m^2")The pair (x, y) (without the addidion of 2*d) can also be easily be determined by using pythagorean_triples(30) as x^2 + y^2 = 30^2. From the pair it is not known which is x and which is y.
Unfortunately (for performance reasons) there is no builtin reverse order in pythagorean_triples(). I am not sure yet how to continue if you know x and y.
LikeLike
Jim Randell 12:11 pm on 5 August 2023 Permalink |
Here’s a solution that starts from possible values of (x − 2d, y):
from enigma import (irange, sum_of_squares, subsets, div, printf) # provide a stream of the permutations of elements in <seq> def permute(seq, select='P'): for ss in seq: yield from subsets(ss, size=len, select=select) # the length of the partition is 30m for (x_, y) in permute(sum_of_squares(900, 2, min_v=2, sep=1)): for b in irange(1, min(y - 1, 14)): h = div(30 * b, y) if h is None: continue a = 15 - b d2 = div(a * y - b * x_, y) if d2 is None or d2 < 2 or d2 % 2 != 0: continue x = x_ + d2 # check area and ratio conditions if not (100 * a * b < 7 * x * y): continue if a * y == x * b or a * x == y * b: continue # calculate the allocation of lawn lawn = (x * y - a * b) * 0.5 printf("lawn allocation = {lawn:g} m^2 [a={a} b={b} d={d} -> x={x} y={y}]", d=d2 // 2)LikeLike
Jim Randell 1:11 pm on 6 August 2023 Permalink |
@Frits: The [[
pythagorean_triples()]] approach is a very efficient way to solve the puzzle.There are only a few triangles that can fit in the vegetable plot, and only (3, 4, 5) gives a viable 2d value. And then one of the orientations is rejected by the area test.
LikeLike
Frits 10:48 pm on 4 August 2023 Permalink |
from enigma import SubstitutedExpression, is_square # invalid digit / symbol assignments d2i = dict() for d in range(0, 10): vs = set() if d == 0: vs.update('A') # bit if d > 1: vs.update('X') # MN < 30 if d > 2: vs.update('M') # PQ < 42 (Situation1 : (PQ - 2 * H)**2 + MN**2 == 900 and H <= 6) if d > 4: vs.update('P') # b = 15 - A <= 14 as A = 1...7 if d > 6: vs.update('GH') if d > 7: vs.update('A') d2i[d] = vs # the alphametic puzzle p = SubstitutedExpression( [ # check 2 situations depending on bit <X> # situation 1 (X = 1): (0, H) is where the partition crosses the y-axis # situation 2 (X = 0): (G, 0) is where the partition crosses the x-axis # length of the partition was 30 metres "X == 1 or P < 3", # if X == 0 then PQ**2 < 900 "PQ < 42", # set variable H to zero if not applicable "X == 1 or H == 0", # length of the partition was 30 metres "X == 0 or div(PQ - is_square(900 - MN**2), 2) == H", # set variable G to zero if not applicable "X == 0 or G == 0", # length of the partition was 30 metres "X == 1 or div(MN - is_square(900 - PQ**2), 2) == G", # garden and plot have dimensions MN by PQ and A by b = 15 - A (A: 1...7) "A < MN < PQ", # plot area is less than 7 per cent of that of the whole garden "100 * A * (b := 15 - A) < 7 * MN * PQ", # different relative dimensions "b * MN != A * PQ", "b < PQ", # situation 1: (0, H) must be on line through (A/2, b/2) and (MN/2, PQ/2) # line y = d.x + H, d = (PQ - b) / (MN - A) # X == 0 or b / 2 - (A / 2) * d == H leads to "X == 0 or A * (PQ - b) == (b - 2 * H) * (MN - A)", # situation 2: (G, x) must be on line through (A/2, b/2) and (MN/2, PQ/2) # line y = d.x + c with c = b / 2 - A * d # X == 1 or d * G + b / 2 - A * d == 0 leads to "X == 1 or 2 * (A - G) * (PQ - b) == b * (MN - A)", ], answer="(MN * PQ - A * b) / 2, (MN, PQ), (A, b), (G, H), X, (PQ - b) / (MN - A)", d2i=d2i, distinct="", reorder=0, verbose=0, # use 256 to see the generated code ) # print answers for ans in p.answers(): print(f"answer: {ans[0] if ans[0] % 1 else int(ans[0])} m^2")LikeLike
Frits 10:53 am on 5 August 2023 Permalink |
A new maximum for the long side of the garden (PQ) seems to be 36. This follows from the x^2 + y^2 = 30^2 formula as mentioned in the text with the alternative approach program.
LikeLike
Hugo 5:35 pm on 13 August 2023 Permalink |
My first idea was a garden 30×14 with a 1-metre-wide strip of vegetable bed along a short side; the dividing line runs across the middle, parallel to the long sides. Though the area of the bed is certainly less than 7% of the total, it’s not exactly in one corner.
Then I remembered Puzzle 213 and soon found the expected solution.
There would be another with the garden 26×24 and the bed 11×4, but its area is then just over 7% of the total. It too involves a 3:4:5 triangle (scaled up sixfold), something I somehow suspected.
LikeLike