Times Table Circles
Place N points around a circle, connect k to k×M modulo N. Animate M and watch cardioids, nephroids, and interference patterns emerge.
The intuition
String art is the simplest version of this idea. Pin equally-spaced nails along two edges of a right angle and number them 1 to 12 outward from the corner. Connect nail 1 on the vertical edge to nail 12 on the horizontal edge, nail 2 to nail 11, nail 3 to nail 10 — each pair sums to 13. Every individual string is straight, but taken together they envelope a curve: a parabola. The rule for which nail connects to which drew the shape; the shape itself was never directly described.
The times-table circle is the same idea with two changes.
First: fold both edges into a single loop. Instead of two separate lines, wrap one line of N points into a circle. Source and destination live on the same ring, so “connecting k to M×k” means drawing a chord across the interior. Wrapping past N just continues around the circle — that’s what mod N means geometrically.
Second: the rule is multiplication. For M = 2, point 1 connects to point 2, point 2 connects to point 4, point 50 connects to point 100 — or, once you pass N, back to wherever 100 mod N lands. Every point gets exactly one chord. The dense bundle of chords, viewed as a whole, has an outline: that outline is the cardioid. M = 3 gives a nephroid; each integer M gives the next epicycloid in the family.
Animating M lets those patterns dissolve into each other. A non-integer M — say 2.3 — connects each point to a fractional position between two labeled dots, interpolating the chord smoothly. As M drifts from 2 to 3, the cardioid’s single inward cusp gradually splits into two, and the nephroid appears. Letting M run continuously is just asking: what does every multiplier between the integers look like?
How it works
Place N points evenly around a circle, numbered 0 to N−1. For each point k, draw a chord to point (k × M) mod N. One multiplication, one remainder — that’s the whole rule.
| M | Named curve |
|---|---|
| 2 | Cardioid |
| 3 | Nephroid |
| 4 | Three-cusped epicycloid |
| 5 | Four-cusped epicycloid |
The editor on the left lets you change the kernel — try adjusting N for denser or sparser patterns, or rewriting lineColor to use a single hue.
Try these
Monochrome glow — replace lineColor with:
function lineColor(k, N, M) {
return `hsl(200, 70%, 65%)`;
}
Radial rainbow locked to M — color rotates with the multiplier:
function lineColor(k, N, M) {
const hue = (k / N) * 360 + M * 30;
return `hsl(${hue % 360}, 80%, 62%)`;
}
Interference — use a non-integer multiplier function:
function multiplier(M) {
return M + Math.sin(M * 0.7) * 0.4;
}
More points — change const N = 200 to const N = 500 for finer patterns.