This Week's Fiddler: Mar 20, 2026

Numerical code used for the extra credit area calculation.

This script samples the stadium boundary to find the two tangency points for each pulled point, solves \(L(r,\phi)=14\) by bisection, and integrates \(A=\frac12\int_0^{2\pi} r(\phi)^2\,d\phi\) using a uniform angular grid.

import math

target_len = 14.0

# Build stadium boundary (two unit circles centered at (-1,0) and (1,0))
points = []
normals = []
seg_lengths = []
steps = 200

# Right semicircle
for i in range(steps + 1):
    t = -math.pi / 2 + math.pi * i / steps
    points.append((1 + math.cos(t), math.sin(t)))
    normals.append((math.cos(t), math.sin(t)))

# Top segment
for i in range(1, steps + 1):
    u = i / steps
    points.append((1 - 2 * u, 1.0))
    normals.append((0.0, 1.0))

# Left semicircle
for i in range(1, steps + 1):
    t = math.pi / 2 + math.pi * i / steps
    points.append((-1 + math.cos(t), math.sin(t)))
    normals.append((math.cos(t), math.sin(t)))

# Bottom segment
for i in range(1, steps + 1):
    u = i / steps
    points.append((-1 + 2 * u, -1.0))
    normals.append((0.0, -1.0))

n = len(points)
for i in range(n):
    j = (i + 1) % n
    dx = points[j][0] - points[i][0]
    dy = points[j][1] - points[i][1]
    seg_lengths.append(math.hypot(dx, dy))

perimeter = sum(seg_lengths)

def visible_arc_indices(px, py):
    visible = [False] * n
    for i in range(n):
        qx, qy = points[i]
        nx, ny = normals[i]
        vx = px - qx
        vy = py - qy
        visible[i] = (vx * nx + vy * ny) >= 0

    max_len = 0
    max_start = 0
    curr = 0
    curr_start = 0
    for i in range(2 * n):
        v = visible[i % n]
        if v:
            if curr == 0:
                curr_start = i
            curr += 1
            if curr > max_len:
                max_len = curr
                max_start = curr_start
        else:
            curr = 0

    if max_len == 0:
        return None

    start = max_start % n
    end = (max_start + max_len - 1) % n
    return start, end

def path_length(start, end):
    length = 0.0
    i = start
    while i != end:
        length += seg_lengths[i]
        i = (i + 1) % n
    return length

def string_length(px, py):
    idx = visible_arc_indices(px, py)
    if not idx:
        return None
    vis_len = path_length(idx[0], idx[1])
    far_len = perimeter - vis_len
    q1 = points[idx[0]]
    q2 = points[idx[1]]
    d1 = math.hypot(px - q1[0], py - q1[1])
    d2 = math.hypot(px - q2[0], py - q2[1])
    return far_len + d1 + d2

def solve_radius(phi):
    lo = 2.0
    hi = 5.0
    Llo = string_length(lo * math.cos(phi), lo * math.sin(phi))
    if Llo is None:
        return None

    while Llo > target_len and lo > 1.2:
        lo -= 0.2
        Llo = string_length(lo * math.cos(phi), lo * math.sin(phi))
        if Llo is None:
            return None

    Lhi = string_length(hi * math.cos(phi), hi * math.sin(phi))
    while Lhi is not None and Lhi < target_len and hi < 8:
        hi += 0.4
        Lhi = string_length(hi * math.cos(phi), hi * math.sin(phi))
    if Lhi is None:
        return None

    for _ in range(40):
        mid = 0.5 * (lo + hi)
        Lmid = string_length(mid * math.cos(phi), mid * math.sin(phi))
        if Lmid is None:
            return None
        if Lmid > target_len:
            hi = mid
        else:
            lo = mid
    return 0.5 * (lo + hi)

def compute_area(samples=720):
    total = 0.0
    for i in range(samples):
        phi = 2 * math.pi * i / samples
        r = solve_radius(phi)
        if r is None:
            continue
        total += r * r
    return 0.5 * total * (2 * math.pi / samples)

area = compute_area()
print(area)

Back to the main post