Skip to content
Vamshi Jandhyala

Books · The Fiddler: Solutions

Chapter 68

Can You Bounce a Ball Like an AI?

A unit square rotates about its centre at constant angular speed. A ball moves at constant speed inside it, reflecting off each edge as though the square were momentarily still. On a special periodic path the ball touches only a single point of the square (never a corner). What is the shortest such path in one loop?

The Fiddler, Zach Wissner-Gross, February 7, 2025(original post)

The ball oscillates along the diameter joining opposite edge midpoints. It strikes the midpoint PP at normal incidence; half a turn later the square has carried PP to the far side, ready to receive the ball again.

Solution

Let the single contact point be the midpoint PP of an edge, a distance 12\tfrac12 from the centre. Send the ball straight along the diameter through the centre and that midpoint. It strikes PP head-on (normal incidence) and reflects straight back. While it travels the length of that diameter, which for a unit square is the edge-to-edge distance 11, let the square turn a half-revolution; then the same edge, carrying the same point PP, has swung to the opposite side, and the ball meets PP again at normal incidence. The motion is a clean oscillation along a fixed diameter. One full period (the square returning to its start, a complete revolution) is two such crossings: L1=1+1=2.L_1=1+1=\boxed{2}.

The computation

Simulate the real thing: a ball of unit speed inside the square spinning at angular speed π\pi (so a half-turn per unit-length crossing), reflecting off whichever edge it reaches. Launched along a diameter through an edge midpoint, it oscillates; the path measures 22 per revolution, and every contact, viewed in the square’s own frame, falls on the same single point.

import numpy as np
w = np.pi; dt = 1e-5; ang0 = np.arange(4) * np.pi / 2
p = np.array([0.0, -0.5]); d = np.array([0.0, 1.0])     # start at a midpoint, moving in
t = path = 0.0; contacts = []; cool = 0
for _ in range(int(6.0 / dt)):                           # three full revolutions
    N = np.c_[np.cos(w * t + ang0), np.sin(w * t + ang0)]
    k = int(np.argmax(N @ p - 0.5))
    if (N @ p - 0.5)[k] >= 0 and d @ N[k] > 0 and cool <= 0:
        d = d - 2 * (d @ N[k]) * N[k]                    # reflect off edge k
        c, s = np.cos(-w * t), np.sin(-w * t)
        contacts.append((c * p[0] - s * p[1], s * p[0] + c * p[1]))   # square frame
        cool = int(0.2 / dt)
    cool -= 1; p = p + d * dt; t += dt; path += dt
print(round(path / 3, 3), np.round(np.array(contacts), 3).tolist())   # 2.0  all (0,-0.5)

Extra Credit

What is the length L2L_2 of the next-shortest single-contact path?

Every contact happens at the point PP, which always sits on its orbit circle of radius 12\tfrac12, so all bounce points lie on that circle and the path is a closed polygon inscribed in it, the square turning through a fixed fraction of a revolution between hits. The diameter is the degenerate two-vertex case; the next paths are genuine inscribed stars whose chord directions still satisfy the reflect-as-if-stationary rule. Pinning down L2L_2 means solving those joint angle conditions, and the value sits behind the source’s paywall, so I leave L2L_2 as a stated open target rather than assert a length I cannot independently confirm.