Juggling looks like a physics problem and is mostly a scheduling one. Before anything leaves a hand there is a question of bookings: a ball thrown now is a promise to catch it on a particular beat, and you have two hands and one beat at a time. Almost everything that makes a pattern hard, and everything that makes a pattern impossible, is decided in that ledger before gravity is consulted.
The whole rule
Write a pattern as the sequence of throws it repeats. A throw is a number: how
many beats until that ball comes back down. 3 forever is the three-ball
cascade. 531 is a five, a three and a one, over and over.
A throw of t made on beat i books the slot (i + t) mod n. That is the
entire legality test:
landings(s) = [ (i + s[i]) mod n for i in 0..n-1 ]
legal ⟺ those are all different
No heights, no hands, no gravity. If two beats book one slot, two balls arrive at the same instant and one of them hits the floor.
Out of it falls a fact that feels like it should cost more than it does. The average of the throws is the number of balls. Not a rule of thumb — an identity. The demo checks it the long way round, following each throw to where it lands until the orbits close and counting the orbits, and compares that to the mean, across every legal pattern of period ≤ 4 with ≤ 4 balls. That is 1270 patterns, and the largest disagreement is exactly zero.
The average is a filter, not a proof
Which tempts you into the obvious shortcut: check the average, and if it comes out whole, juggle it. It does not work, and the counterexample is three digits long.
543 averages exactly 4. It also puts every one of its three throws on the
same landing:
beat 0 throws 5 → slot (0+5) mod 3 = 2
beat 1 throws 4 → slot (1+4) mod 3 = 2
beat 2 throws 3 → slot (2+3) mod 3 = 2
Three balls, one landing, one pair of hands. Feed 5 4 3 to the demo by hand
and it drops on beat 1 — you do not even get to the third throw.
And the shortcut is not close to right in bulk either. Over period-4 sequences of digits 0–9: 2498 of the 10000 have a whole-number average, and 962 of those juggle. The average test throws away three quarters of everything, and then for every pattern it is right about it waves through 1.6 that drop. At period 3 it does better — 334 whole, 226 juggleable, 67.7% — which is exactly the trap, because period 3 is where you would go looking for confidence.
How many patterns there are
The census view enumerates them, and the count that comes back is not the ragged number you would expect from a constraint that awkward:
period n, at most b balls → exactly (b + 1)ⁿ patterns
Period 4 with at most 4 balls: 625. Period 5 with at most 4: 3125. The demo checks seven of these by brute force and they land on the nose every time. Subtract to get the ones using exactly that many balls — 625 − 256 = 369 four-ball patterns of period 4. This is a known theorem (Buhler, Eisenbud, Graham and Wright); what the demo adds is watching it come out of an enumeration rather than being told.
(b+1)ⁿ is the number of strings of length n over b+1 symbols. So there
are exactly as many juggling patterns as there are ways to write down n
digits from a (b+1)-letter alphabet — while the patterns themselves are a
thin, scattered subset of the sequences you can actually write. The counting
is trivial and the membership is not, which is an unusual way for a set to
behave.
Where the game is
Take the hands over — press a digit — and you are feeding throws into the same ledger. Two things immediately bite.
The first is the average, now as a budget rather than a theorem. Your throws
must average your ball count, so a 5 is borrowing and something has to repay
it. In three balls, a 5 is repaid by a 1.
The second is sharper, and it is the thing nobody tells you. The three-ball ground state has the next three beats already booked:
state 1 1 1 0 0 0 0 0 0 legal throws: 3 4 5 6 7 8 9
From a cascade you cannot throw a 1, and you cannot throw a 2. Beats 1 and
2 are spoken for. The low throws are not something you are bad at; they are
unavailable. To make one you first have to throw something high enough to open
the slot, which is what 531 actually is — the 5 is what buys the 1, three
beats later. That is the loop the mechanic runs on: you can only spend what a
previous throw made room for, and the readout of your running average creeping
onto your ball count is the receipt.
One more thing the state graph says, which is easy to miss and hard to unsee:
throwing never changes how many slots are booked. So 3, 441, 531 and
423 all sit in one state and interchange freely — the transition between
them is the empty list, there is nothing to do — while the transition from
three balls to four does not exist. Adding a ball is not a juggling move.
It is a different pattern, started from scratch.
Then the hands get involved
A beat is a duration. A ball lands D seconds before the beat it is thrown
on, is held for D, and is in the air for the rest:
flight(t) = t·beat − D height = g·F²/8
With two hands taking turns, a hand is busy for D and idle for
V = 2·beat − D, and those four durations are locked together by an identity
Claude Shannon wrote down while building a juggling machine:
(flight + dwell) · hands = (vacant + dwell) · balls
The demo holds it across 1890 combinations of ball count, tempo and dwell, to 3.5 × 10⁻¹⁶ relative — it is bookkeeping, not a model, and it is the reason you can only ever trade these things against each other.
Five balls is four times as high
Hold your hand rhythm fixed and add a ball. Flight time goes up by one beat, so
height — which goes as flight squared — goes as (n − d)², where d is the
dwell as a fraction of a beat. Not as n. At a one-beat dwell the numbers come
out whole:
3 balls → ×1
5 balls → ×4.00
7 balls → ×9.00
9 balls → ×16.00
At a gentler 0.75-beat dwell it is ×3.57 for five, and with no dwell at all — an instantaneous hand, which nobody has — the best case is still ×2.78. There is no dwell anywhere that makes five balls ×1.67 of three. Everyone’s first instinct is the dashed grey line in that panel, and the orange curve leaves it immediately.
This is also why the scene goes off the top of the screen when you load
97531: at the tempo that suits a cascade, its nine peaks at 6.5 m. The
demo draws where three balls would reach on the same hands as a dashed line
near the floor, so the spike means something. Press N and it solves for the
tempo that would put that nine at 1.5 m instead, which is the only other thing
hands can do.
What actually runs out
Here is the part worth taking away. Fix the height you are willing to throw — say 1.50 m, which is 1106 ms of flight. Vacant time cannot go negative, because a hand cannot be in two places, and that alone caps the pattern:
N ≤ hands · (flight + dwell) / dwell
dwell 400 ms → 7 balls
dwell 300 ms → 9
dwell 200 ms → 13
dwell 100 ms → 24
A 300 ms dwell caps a 1.50 m pattern at nine balls, and no amount of arm fixes it. Take 100 ms off the dwell and you get four more. Try to buy those same four balls with height instead, keeping the slow hand, and you need to throw 3.34 m — ×2.22 as high — for the identical result.
So the limiting organ is the hand, not the arm. The thing you would train is not throwing power and not even catching accuracy; it is how briefly you can hold a ball and still control where it goes. That is a strange conclusion to reach from a gravity problem, and it is the one Shannon’s identity forces.
And the precision bill
There is a second cost, and it compounds. A throw with a relative error σ in
launch speed has a proportional error in flight time — δF = σ·F — because
F = 2v/g is linear in speed. Flight time grows with the pattern. The catch
window does not. So:
60 ms window, 0.75-beat dwell:
3 balls needs throws inside 3.17%
7 balls needs throws inside 1.14% ×2.78 more consistent
Simulated rather than asserted: the same hands, throwing at a fixed 2% error, last 3994 beats on three balls — against a 4000-beat cap, so essentially forever — 92 on five, and 10 on seven. The pattern does not get harder gradually. It falls off a cliff, because a constant relative error is an absolute error that grows.
Driving it
Three views, V cycles. hands runs a pattern — the scene, the ladder
(every throw an arc from the beat it left to the beat it lands on, so a
collision would be two arcs touching down on one dot), and the live landing
schedule with the legal throws marked. wall is the two physics panels.
census is every pattern of a period, with X mixing in the near-misses
that pass the average test and drop anyway.
In hands: 0–9 throws, and the first digit you press takes the hands off
the autopilot; A gives them back. [ ] change pattern, ↑ ↓ the tempo,
← → the dwell, N solves for the tempo the pattern would really need,
space runs and pauses. In census: ← → move the cursor, [ ] the
period, ↑ ↓ the ball cap, Enter sends the selected pattern to the hands.
What the model does not do
- One ball per hand, two hands, one beat each. No multiplex throws (two balls from one hand at once), no synchronous patterns, no more than two hands — all of which siteswap has notation for and none of which is here.
- Dwell is one number. Real dwell varies with the throw: you hold a high
throw longer than a low one, which is precisely why the constant-
dcurves above are the optimistic case. - No air resistance, no spin, no hand travel time. The hand teleports between its catch point and its throw point over the dwell, and the ball is a point.
- The precision numbers use a fixed catch window — 60 ms, a plausible figure rather than a measured one. The ratios between ball counts do not depend on it, which is the part being claimed; the absolute percentages do.
- A drop here is a scheduling failure, not a dropped catch. The manual mode never misses a ball it was allowed to throw; it only ever fails because the throw booked an occupied slot, or because nothing was queued. That is a narrower game than juggling, on purpose.
Reusing it
src/dwell.mjs is framework-free and has no DOM in it. Seconds, metres, m/s.
import { parse, isValid, mean, ballCount, census, stateOf, legal, schedule, shannon, ceiling } from './dwell.mjs';
isValid(parse('531')); // true
isValid(parse('543')); // false — average 4, three balls on one slot
ballCount(parse('97531')); // 5, found by following orbits, not by averaging
census(4, 4).length; // 625 = (4+1)^4
legal(stateOf(parse('3'), 9)); // [3,4,5,6,7,8,9] — no 1, no 2
schedule(parse('531'), { beat: 0.28, dwell: 0.21 }); // timed throws with heights
shannon({ balls: 5, beat: 0.28, dwell: 0.21 }).vacant; // what the hand has left
ceiling({ flight: 1.106, dwell: 0.3 }); // 9.37 balls, hard stop
The scheduling half is useful well away from juggling: stateOf / legal /
advance is a small bounded-resource allocator — a window of future slots, a
move that books one, and a legality test that is just “is it free” — and
transition is breadth-first search over those states. Anything that has to
place work on a timeline without double-booking it has the same shape.
node scripts/screenshot-demo.mjs boots the demo in a real Chromium, drives it
through its own hooks, and checks all 47 of the claims above against the
running code before it writes a single screenshot.



