Rewriting an alphabet, generation by generation
An L-system (Lindenmayer system) is a formal grammar: an alphabet of symbols, a starting string called the axiom, and a set of production rules that say what each symbol should be replaced by. Aristid Lindenmayer introduced them in 1968 to model the growth of algae. The crucial difference from a Chomsky grammar used to parse programming languages is that every symbol in the string is rewritten simultaneously, generation after generation, rather than one substitution applied at a time — which mirrors how every cell in a growing organism divides at once.
axiom: F rule: F -> F+F--F+F angle: 60 degrees gen 0: F gen 1: F+F--F+F gen 2: F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F (Koch-style curve)
Turtle graphics: turning symbols into geometry
The rewritten string means nothing until it is drawn, and that is the job of a turtle that walks across the canvas obeying each symbol in order: F moves forward while drawing a line, f moves forward without drawing, + and - turn the turtle left or right by a fixed angle, and [ / ] push and pop the turtle's position and heading onto a stack. That stack is what turns a single string into a branching structure: the turtle draws one branch, brackets back to the fork point, and starts the next branch from exactly where it left off.
for symbol in string:
if symbol == 'F': drawLineForward(stepLength);
if symbol == 'f': moveForward(stepLength)
if symbol == '+': heading += angle
if symbol == '-': heading -= angle
if symbol == '[': stack.push({pos, heading})
if symbol == ']': {pos, heading} = stack.pop()
Stochastic and parametric extensions
A plain L-system is exactly self-similar, which looks geometric rather than organic. Stochastic L-systems fix that by giving several possible replacements for a symbol, each with its own probability, so no two branches unfold identically — this is how Barnsley's fern gets its natural, irregular look from a purely random rule choice at every step. Parametric L-systems attach numeric parameters to symbols (branch length, thickness, angle) that shrink or vary with each generation, letting a tree taper realistically as it grows outward, and context-sensitive variants let a symbol's rewrite depend on its neighbours, approximating how real plant hormones signal growth between adjacent cells.
Famous examples and their rules
Koch snowflake F->F+F--F+F angle 60 Dragon curve X->X+YF+ Y->-FX-Y angle 90 Sierpinski tri. F->G-F-G G->F+G+F angle 60 Barnsley fern (parametric, 4 stochastic affine transforms) Hilbert curve A->-BF+AFA+FB- B->+AF-BFB-FA+ angle 90
Why it scales: complexity from short strings
A rule that replaces one symbol with k symbols makes the string grow roughly like k^n after n generations — exponential growth from a rule you could write on a napkin. That is the entire appeal of the model: a few characters of grammar, applied recursively, generate the same kind of branching self-similarity biologists see in real ferns, bronchial trees and river deltas. Prusinkiewicz and Lindenmayer catalogued this connection thoroughly in The Algorithmic Beauty of Plants, still the standard reference for anyone building a botanically plausible L-system.
Frequently asked questions
What do the square brackets in an L-system rule mean?
They tell the turtle to save or restore its state. [ pushes the current position and heading onto a stack; ] pops the stack, returning the turtle to that saved position and heading. That is how a single string produces a branching tree instead of one continuous line: the turtle draws a branch, brackets back to the fork, and starts the next branch from the same point.
Why do L-system trees look more like real plants than hand-drawn fractals?
Aristid Lindenmayer originally designed L-systems in 1968 to model how real algae and plant cells actually divide and grow, not to make pretty pictures. Parametric and stochastic extensions let branch length taper with each generation and let angles vary randomly within a range, which mimics the biological variability of real growth far better than a rigid, exactly self-similar fractal.
Why does the string length explode so fast?
Because every symbol in the string is rewritten in parallel, every generation, according to its production rule. If a rule replaces one symbol with k symbols, the string length roughly multiplies by k each generation, so length grows exponentially in the number of generations even though the rule itself is just a few characters long.
Try it live
Everything above runs in your browser — open L-System Fractals and change the parameters while it is running. Nothing is installed, nothing is uploaded, the whole model lives in one tab.
▶ Open L-System Fractals simulation