Teaser 2417: [Flower bed]
From The Sunday Times, 18th January 2009 [link]
Old Mellors, the estate gardener, has designed a large flower bed. He has marked out two overlapping circles whose radii differ by one metre: the bed consists of the area within one or both of the circles. He wants to plant various straight lines of seeds in the flower bed. The longest such possible is 25 metres long; if he wants the line to touch the perimeter of the bed in three places, then the longest possible is 22 metres.
What are the radii of the circles?
This puzzle was originally published with no title.
[teaser2417]
Jim Randell 8:08 am on 13 May 2026 Permalink |
If we suppose the circle have radii R and r, where R ≥ r, then:
For the circles to overlap the distance d between their centres must be:
In this case we have R = r + 1, so:
The longest possible line is 25, so:
Hence:
and:
So we have bounds on possible values for r, we can look for situations where the maximum line through an intersection is 22 m.
First I defined some additional 2D geometry functions to help with circles:
Circle = namedtuple('Circle', 'centre radius') # find intersection points of circle <c> # with the line defined by points <p1>, <p2> # may return 0, 1, 2 points def circle_intersect_line(c, p1, p2): (((x0, y0), r), (x1, y1), (x2, y2)) = (c, p1, p2) (xd, yd) = (x2 - x1, y2 - y1) # construct a polynomial for the intersection f = sq(Polynomial([x1 - x0, xd])) + sq(Polynomial([y1 - y0, yd])) ts = f.roots(sq(r), domain='F') return list(P2(x1 + t * xd, y1 + t * yd) for t in ts) # parameterised circle t = -1 to +1 for a full circle # 0 = 3 o'clock; 0 -> 1 = anticlockwise to 9 o'clock; 0 -> -1 = clockwise to 9 o'clock def circle_param(c, t=None): ((x, y), r) = c f = lambda t, x=x, y=y, r=r: P2(x + r * math.cos(t * pi), y + r * math.sin(t * pi)) return (f if t is None else f(t)) # find <t> parameter for point <p> on circle centre <c> radius <r> def circle_param_t(c, p, t=1e-9): (o, r) = c if not (abs(point_dist(o, p) - r) < t): return None ((x0, y0), (x, y)) = (o, p) t = math.acos(fdiv(x - x0, r)) / pi return min(t, -t, key=(lambda t: abs(point_dist(circle_param(c, t), p))))(These functions are in the latest version of enigma.py).
The following Python program solves the problem constructively. Given a value for r (the radius of the smaller circle) it first derives the values of R (the radius of the larger circle) and d (the separation between the centres), and then finds P (one of the intersection points of the circle). It then extends the tangent to the smaller circle at P to intersect with the larger circle at Q.
We then look for a point A on the circumference of the larger circle between P and Q, and extend AP to a point B on the smaller circle. And we choose A so to maximise the length of AB (using the [[
find_max()]] function from the enigma.py library.We can then use the [[
find_values()]] function from the enigma.py library to determine what value of r gives a maximum AB of 22.It runs in 220ms. (Internal runtime is 151ms).
from enigma import ( Circle, circle_intersect_line, circle_param, circle_param_t, triangle_point, point_dist, line_param, line_bisect, find_max, find_values, call, item, printf ) # extract leftmost and rightmost points from a sequence leftmost = lambda pts: (min(pts, key=item(0)) if pts else None) rightmost = lambda pts: (max(pts, key=item(0)) if pts else None) # find maximum length line through intersection point P, given <r> def solve(r): # larger circle radius is 1 m larger R = r + 1 # distance between circle centres d = 24 - 2*r # specify the two circles (centre, radius) (CR, Cr) = (Circle((0, 0), R), Circle((d, 0), r)) # find the upper intersection point = P P = triangle_point(d, R, r) # and the corresponding start <t> parameter on the larger circle tP = circle_param_t(CR, P) # calculate the tangent to the smaller circle at P f = line_param(Cr.centre, P) (p1, p2) = line_bisect(f(0), f(2)) # and where it intersects the larger circle at Q Q = leftmost(circle_intersect_line(CR, p1, p2)) # and the finish <t> parameter on the larger circle tQ = circle_param_t(CR, Q) if tQ < tP: tQ += 2 # points on the larger circle parameterised by <t> fR = circle_param(CR) # find the A, B intersection points for A at parameter <t> def fAB(t): # A is on the larger circle A = fR(t) # the line from A extends through P and intersects the smaller circle at B B = rightmost(circle_intersect_line(Cr, A, P)) return (A, B) # find the maximum length AB line for <t> parameters between P and Q m = find_max((lambda t: call(point_dist, fAB(t))), tP, tQ) # return the maximal value return m.fv # find <r> when the max line through an intersection point is 22 for s in find_values(solve, 22.0, 5.75, 11.5): # determine parameters r = s.v R = r + 1 d = 24 - 2*r printf("r = {r:.2f}; R = {R:.2f}; d = {d:.2f}")Solution: The radii of the circles are 6.5 m and 7.5 m.
And the distance between the centres of the circles is 11 m.
Manually:
Suppose the centres of the circles are separated by a distance d.
Then we can plot the circles as follows:
We can draw a straight line L through P at an angle of 𝛉.
At a distance t (negative to the left and positive to the right) it has the following parametric equation:
The intersection with the larger circle (A) is given when t ≠ 0 and:
So the distance AP is given by:
Similarly the intersection with the small circle (B) is given by:
So the distance BP is given by:
And so the total distance AB is:
From which we see the distance AB achieves a maximum when 𝛉 = 0 (i.e. when the line is horizontal [*]), and the maximum value is twice the distance between the centres of the circles.
We can now apply this finding to the puzzle.
The maximum length line through the intersection is 22 m, hence the distance between the circles is 11 m.
And the maximum length line between two points on the perimeter of the bed is 25 m.
Hence:
And the solution follows.
[*] However, not all configurations permit a horizontal line to be drawn, in which case the maximum length line is given by the tangent to the smaller circle (PQ), with the angle increased infinitesimally to permit the line to intercept the perimeter of the combined shape at 3 distinct points.
For example:
LikeLike