DEFINITION
aᵢ′ = aᵢ₋₁ XOR (aᵢ OR aᵢ₊₁)
NOTES
A one-dimensional automaton, one line of cells, each new row derived from the one above by looking at three neighbours. From a single black cell it produces a pattern with a provably random-looking centre column — random enough that Mathematica used it as a pseudo-random generator for years. Nobody has proved it never repeats.
PROVENANCE
- Origin
- S. Wolfram, "Statistical Mechanics of Cellular Automata", 1983
- Standing
- The rule is public domain. Wolfram's book text is not; his rules are.
- Constants
- Rule number 0–255 selects one of the 256 elementary automata
- Source
- doi:10.1103/RevModPhys.55.601
HOUDINI · VEX
The same published mathematics as a Detail Wrangle body. Paste it into a Wrangle with Run Over set to Detail; every constant is the published value plus a tweak channel, so Create Spare Parameters gives a slider that starts where the paper does.
// FORMA — PL. 25 · RULE 30 — Stephen Wolfram, 1983
// aᵢ′ = aᵢ₋₁ XOR (aᵢ OR aᵢ₊₁)
// Paste into a Detail Wrangle (Run Over: Detail), no inputs needed.
// Written from the published mathematics, not adapted from any code.
// Constants arrive at their published values. Press the node's Create
// Spare Parameters button and every tweak becomes a slider — starting
// at 0, the published figure, and moving in the constant's own units.
// https://forma-gen.com/#plate=rule30
float p_rule = 30 + chf('rule_tweak'); // rule number · live 0 .. 255
float p_width = 220 + chf('width_tweak'); // cells across · live 80 .. 400
float p_seed = 0 + chf('seed_tweak'); // random seed row · live 0 .. 1
// The plate's own colour: FORMA's AUTOMATA accent as a cosine ramp,
// brightest near t = 0 and t = 1, near-black around t = 0.5.
vector forma_ramp(float t){
return set(
0.3301 + 0.3588 * cos(6.28318530718 * (t + 0)),
0.2255 + 0.2451 * cos(6.28318530718 * (t + 0.05)),
0.46 + 0.5 * cos(6.28318530718 * (t + 0.1)));
}
// One line of cells and a three-neighbour rule, run down the cloth: the
// space-time diagram of an elementary automaton, one point per set cell —
// shell's idiom, for the automaton that started the classification. The
// rule number's eight bits are read arithmetically because VEX has no bit
// shifts; the wrap at the row ends is the plate's own. The plate grows the
// diagram over its clock and lights the newest rows in HILITE — a growth
// cursor, not part of the finished diagram, so neither is ported. As many
// rows as cells, the square cloth the plate cuts at a square card.
// Deterministic: the random seed row option draws random(counted seed) on
// the plate's own seed.
int n = int(rint(p_width));
int rows = n;
int rule = int(rint(p_rule));
int pw[] = {1, 2, 4, 8, 16, 32, 64, 128}; // bit weights, since VEX has no shifts
int row[];
resize(row, n);
if (int(rint(p_seed)) != 0){
int rc = 30; // the plate's own seed, counted upward
for (int i = 0; i < n; i++){ row[i] = random(rc) < 0.5 ? 1 : 0; rc++; }
} else {
row[n / 2] = 1; // the single black cell of the famous figure
}
for (int y = 0; y < rows; y++){
for (int x = 0; x < n; x++){
if (!row[x]) continue;
// canvas y runs down; negated so time runs downward as the plate shows it
int pt = addpoint(0, set(float(x - n / 2), -float(y), 0.0));
setpointattrib(0, "Cd", pt, forma_ramp(float(y) / float(rows) * 0.5 + 0.1));
}
int next[];
resize(next, n);
for (int x = 0; x < n; x++){
int l = row[(x - 1 + n) % n], c = row[x], r = row[(x + 1) % n];
next[x] = (rule / pw[l * 4 + c * 2 + r]) % 2;
}
row = next;
}
AFTER EFFECTS · DECLINED
Cells, not a path: one filled square per live cell of a space-time diagram, which a stroke cannot carry.