L-Systems: A Grammar for Growth
A biologist's model of algae growth turns out to be the cleanest possible generalisation of the Koch and dragon constructions.
History
Every fractal so far was invented as pure mathematics. The Lindenmayer system breaks that pattern: biologist Aristid Lindenmayer invented it in 1968 not to explore geometry, but to model how a filament of algae actually grows, cell by cell. His insight — a growth rule applies simultaneously, everywhere — is exactly the “replace every piece at once” idea already driving Koch and dragon curves, just written as a rewrite rule on symbols instead of line segments.
Lindenmayer was a biologist, not a mathematician, and his 1968 papers were published in the Journal of Theoretical Biology. It took over a decade, and Alvy Ray Smith’s 1984 computer-graphics paper, before anyone noticed his grammar for algae was also a remarkably good grammar for pictures.
What is turtle geometry?
Every L-system needs something to actually turn its symbols into a picture, and that something is almost always a turtle — a tiny robot that remembers exactly two things: where it is, and which way it’s facing. It only understands a handful of commands:
| Command | What the turtle does |
|---|---|
F | walk forward one step, drawing a line as it goes |
+ | turn left by a fixed angle |
- | turn right by that same angle |
That’s it. No coordinates, no trigonometry to write by hand — the
turtle handles all of that internally. You just hand it a string of
Fs, +s, and -s, one character at a time, and it walks and turns
its way across the page. The idea dates back to Seymour Papert’s Logo
language in the late 1960s (the same era as Lindenmayer’s own work),
and it turned out to be exactly the right tool for reading an
L-system’s rewritten string: the turtle doesn’t know or care that
the string came from a grammar rather than a person typing commands by
hand.
The axiom and the rules
Every L-system is just two ingredients:
- The axiom — the starting string. Nothing more than what the turtle is handed on generation zero, before any rewriting happens.
- The rules — a lookup table saying what each symbol turns into,
applied to every matching symbol in the string simultaneously,
once per generation. A symbol with no rule (like
+or-) just carries over unchanged.
Apply the rules once to the axiom, and you get generation one. Apply them to generation one, and you get generation two. Do this enough times and hand the final string to the turtle, and — for the right rules — you get a fractal.
Warm-up: drawing a square and a triangle
Before any of that rewriting, it’s worth seeing the turtle draw something with no rules at all — just an axiom, walked once. A square is simply “walk forward, turn 90°, four times”:
Axiom F+F+F+F, angle 90° — no rules needed yet. Each F is one
forward step; each + is one left turn. Follow the arrows in order and
you’ve traced the whole square, back to where you started.
A triangle is the same idea, just three sides and a sharper turn — the turtle has to turn more at each corner (120° instead of 90°) to still end up facing its start direction after only three turns instead of four:
Axiom F+F+F, angle 120°. The general rule: for any regular polygon
with sides, the turn angle is — a square turns
90° four times, a triangle turns 120° three times, both totalling one
full 360° turn by the time the turtle gets home.
Neither of these used a rule — the axiom was the entire instruction
list, walked exactly once. This is the piece L-systems add on top:
instead of writing out F+F+F+F by hand, you write an axiom and a
rule, let the rewriting happen automatically, generation after
generation, and only then hand the (now much longer) result to the
same turtle. The turtle itself never changes; only the string it’s
given gets more elaborate.
Construction
An L-system rewrites a string generation by generation, then hands the result to the turtle described above. The [ / ] pair is the one command not yet introduced — push / pop (position, heading), for branching. It lets the turtle finish a branch, jump back to wherever it last saved its position, and start a new one — which the square, the triangle, and single continuous curves like Koch and dragon never needed, since they never have to “return” anywhere.
The Koch curve is secretly an L-system: axiom F, rule F → F+F--F+F, angle 60°. Every “replace every segment with a fixed pattern, forever” fractal has an L-system encoding.
Python implementation
Pseudocode first
rewrite(word, rules, n) {
repeat n times
word = replace every symbol simultaneously
return word
}
turtle(word) {
F: forward; +: left; -: right; [: push; ]: pop
}
The executable version keeps the same shape; shared plotting/export details live in fractalfair_helpers.py.
def rewrite(axiom, rules, iterations):
word = axiom
for _ in range(iterations):
word = "".join(rules.get(ch, ch) for ch in word)
return word
# turtle_segments() then interprets F, +, -, [, ]
go (c:cs) pos heading stack acc = case c of
'[' -> go cs pos heading ((pos, heading) : stack) acc
']' -> case stack of
((p, h) : rest) -> go cs p h rest acc
[] -> go cs pos heading stack acc
...
Figure: Six generations of X → F+[[X]-X]-F[-FX]+X, angle 25° — a completely different mechanism from the Barnsley fern, arriving at an equally organic result.