L-System Discovered 1968

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.

Anecdote

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:

CommandWhat the turtle does
Fwalk 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”:

A turtle drawing a square: four F commands with 90-degree turns

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:

A turtle drawing a triangle: three F commands with 120-degree turns

Axiom F+F+F, angle 120°. The general rule: for any regular polygon with nn sides, the turn angle is 360/n360^\circ / n — 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.

Cool Fact

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

Algorithm in one glance Rewrite
Grow a string, then walk it
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, +, -, [, ]
λThe Same Idea in Haskell
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
  ...
Bracketed L-system fractal tree

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.