Maybe you've never heard of Typogenetics before or maybe you're a long-time fan of Douglas Hofstadter's Pulitzer Prize-winning book Gödel, Escher, Bach: An Eternal Golden Braid. Either way, this blog post is for you.
What's Typogenetics?
Typogenetics, short for "typographical genetics", is a simplification of biology. It's an artificial system that explores some of the coolest computational features of genetics while ignoring much of the messy chemistry and physics.
Over the next few sections, we'll lay out the rules of Typogenetics, starting simple and slowly adding complexity. Throughout, I'll provide visualizations where I think they may help.
Building blocks
All life on Earth has DNA built from four molecules: Adenine (A), Cytosine (C), Guanine (G), and Thymine (T). These are called nucleobases, but in the spirit of simplification, Typogenetics calls these bases. And don't worry about the molecular names or the underlying chemistry of these molecules. For our purposes, all we care about is the letters A, C, G, and T.
Figure 1: Bases — The four bases and their two groups: A and G are both called "purines" and C and T are "pyrimidines".
If we string a few of these bases together we'll call that a strand. Each position along a strand is called a unit.
Figure 2: Strands — Bases strung together in any order form a strand.
Rewriting
Typogenetics defines a small set of rules that, when applied to a strand, rewrite it into a new strand. Each rule is called an amino acid. A sequence of these rules is called an enzyme. Let's look at an example of an enzyme made up of three amino acids:
- Rule 1 -- del: Delete the base to which the enzyme is bound (and then bind to the next unit to the right).
- Rule 2 -- mvr: Move one unit to the right.
- Rule 3 -- int: Insert a T (to the immediate right of this unit).
Your browser does not support the video tag.
Figure 3:
Rewriting — In this simple example, the del-mvr-int enzyme rewrites ACA to CAT.
A very useful amino acid is called cut, which slices a strand to the right of the current unit, producing two strands.
Your browser does not support the video tag.
Figure 4:
Cut — The cut amino acid slices a strand into two. In this example, mvr-mvr-cut moves two units to the right and then performs a cut.
Another useful amino acid is cop, which turns on "Copy mode". When Copy mode is on, new bases bind to the current strand. Specifically, A binds to T, and C binds to G. These are called complementary base pairs. When Copy mode is on, any time the enzyme moves left or right, a new complementary base is added to the other strand.
> Note that the complementary strand is built mirroring our current strand, so we flip it at the end to read it left to right.
Your browser does not support the video tag.
Figure 5:
Copy — Copy mode allows enzymes to duplicate strands. In this case, cop-mvr-mvr-mvr-mvr-mvr turns Copy mode on and then walks down the current strand, creating a complementary strand in the process.
Next let's see what happens if we cut while the strand is being copied. You can see that we get a couple of free-floating strand fragments. A single enzyme acting on a single strand can produce many strands as output.
Your browser does not support the video tag.
Figure 6:
Copy and cut — Cutting a strand while Copy mode is enabled can produce many strands.
Closing the loop with translation
Fans of Typogenetics (and biologists) will have predicted this next magical step. We create a mapping between amino acids and pairs of bases, called duplets.
Figure 7: Amino acids — This table shows the mapping from pairs of bases to their corresponding amino acids.
Now, not only can enzymes operate on strands, but those same strands can themselves be treated as enzymes. All we need to do is take a strand, use this chart to convert duplets into amino acids, and we have a new enzyme that can itself operate on strands. This process is called translation.
> Note: The AA duplet does not code for an amino acid. It is reserved as a "punctuation mark" to mean "end of enzyme". Multiple amino acid sequences can be created from a single strand during translation.
Your browser does not support the video tag.
Figure 8:
Translation — A chain of amino acids is constructed by decoding pairs of bases.
Folding
The animation above shows an enzyme being constructed as a straight chain of amino acids. However, Typogenetics introduces a bit more complexity. Each amino acid has the possibility of inducing a 90° kink in the enzyme. The letters r, l, and s in Figure 9 indicate whether the amino acid will cause the enzyme to fold right, left, or straight.
Review Figure 7 to see the folding behavior of every amino acid in Typogenetics.
Your browser does not support the video tag.
Figure 9:
Folding — Akin to real-life protein folding, Typogenetics adds some higher-level structure to enzymes by introducing 90° kinks to amino acid chains.
Binding preference
The folding structure of enzymes in Typogenetics isn't just for fun. We use this structure to determine which base on a strand the enzyme should bind to initially. Holding the orientation of the first segment to the right, the orientation of the last segment determines the binding preference of the enzyme.
The ultimate function of the enzyme depends on small contributions from all amino acids, similar to how the 3D structure of a protein determines its function in real biology.
Figure 10: Binding preferences — The relative orientation of the first and last segments of an enzyme's secondary/tertiary structure determines the binding-preference of the enzyme.
Filling in the details
At this point, we've covered all the major design features of Typogenetics, capturing the essence of the central dogma of molecular biology.
If you're inspired to implement Typogenetics yourself, you'll need a bit more info to make sure all edge cases are well-defined. If you want to skip the nitty gritty details, you can jump to the next section.
Show me the details ||| Hide the details
Table of amino acid rewrite rules
| Amino Acid | Rule |
| ----------------------------- | ---------------------------------------------- |
| cut | cut strand(s) |
| del | delete a base from strand |
| swi | switch enzyme to other strand |
| mvr | move one unit to the right |
| mvl | move one unit to the left |
| cop | turn on Copy mode |
| off | turn off Copy mode |
| ina | insert A to the right of this unit |
| inc | insert C to the right of this unit |
| ing | insert G to the right of this unit |
| int | insert T to the right of this unit |
| rpy | search for the nearest pyrimidine to the right |
| rpu | search for the nearest purine to the right |
| lpy | search for the nearest pyrimidine to the left |
| lpu | search for the nearest purine to the left |
Clarifications
- cut applies to both strands.
- del applies to only the strand on which the enzyme is working.
- swi moves the enzyme to the attached strand above the current strand. If there is no complementary base where the enzyme is currently bound, then the enzyme just detaches itself.
- Insertion instructions will insert into both strands if Copy mode is on (with the complement inserted into the other strand). If Copy mode is off, then a blank space is left in the complementary strand.
- If Copy mode is on and move or search instructions are encountered, then complementary bases should be manufactured everywhere the current strand slides.
Try it out
I've implemented a command-line interface for Typogenetics. You can test translation from strands to enzymes and the application of enzymes to strands. You can also simulate many generations of rewrites either with open-ended search or looking for a particular enzyme function.
In these next two sections, I want to explore some loose connections to other areas that are analogous to Typogenetics and consider implications of potential tweaks to the system.
Connections
Turing completeness
While I have not found anything definitive about whether Typogenetics is Turing complete, I would not be surprised if it were proven to be Turing incomplete. While there is certainly the ability to write to a tape, the lack of a set of states for the machine to be in makes me pessimistic. Endowing an enzyme with a small finite state machine could be an interesting way to increase its representational power.
Sequence-to-sequence modeling
Would it be possible to train a sequence-to-sequence model to apply an enzyme to a strand with the same rules as Typogenetics? Many instructions seem difficult to me to represent, but perhaps there's a recurrent architecture that could represent the full instruction set.
Parallelism
Without changing the specification of Typogenetics at all, it would be cool to speed up its execution by parallelizing. While each rewrite step is fundamentally serial, the processing of strands is an embarrassingly parallel operation. Especially if selection of strands and enzymes to interact is completely random, we are guaranteed to have no race conditions.
Adding a spatial dimension
Inspired by Axelrod and Hamilton on the evolution of cooperation and Nowak and May on spatial evolutionary games, you could limit strands to move around a "physical" space. Requiring interactions between enzymes and strands to be limited to spatially local interactions might promote more variation in evolved structures. More variation might come at the cost of lower complexity at first, but I can imagine some very improbable yet very destructive enzymes dominating if their radius of interaction is effectively infinite. Akin to ancient hydrothermal vents, rare pockets of fertile quiet may be necessary for fragile complexity to emerge slowly, undisturbed by its chaotic environment.
Tuning
Many find it incredible that John Horton Conway's Game of Life can produce and maintain so much complexity with such simple rules. In an interview with the Numberphile YouTube channel, Conway explains that the rules of the Game of Life were discovered through a process of trial and error.
> "[The Game of Life] was different for quite a long time. We tinkered with these rules and finally came up with the ones I said. And they really seemed to have very nice properties. Namely [we] didn't seem to be able to predict what would happen. And in the end we succeeded in proving essentially anything could happen. These things could do any kind of computation you wanted to do." -- John Horton Conway
I interpret Conway to be saying that the Game of Life's complexity is really not that surprising given that the rules of the game were specifically selected in order to elicit that behavior. It's unclear to me how much the rules were selected with blind tuning versus mathematical derivation. Regardless, it has always intrigued me that when a complex system doesn't produce interesting behavior right away, the fix may be tuning rather than redesign.
Is there a way to parameterize the instructions of Typogenetics in such a way that they become tunable? Is there a metric we can optimize toward once we do have tunable instructions?
Genotype networks
Informed by Andreas Wagner's research, you could model the space of enzymes. A genotype is close to another genotype in genotype space if their edit distance is small. But exploration of this space to find another genotype with the same phenotype (enzyme function) is relatively easy given all of the dimensions (units of a strand) along which we can search.
As Wagner explains in Arrival of the Fittest, you're looking for many needles in the same haystack. If this theory is correct, it should be very easy to cross vast distances in genotype space (large strand edit distance) while remaining stationary in phenotype space (coding for the same enzyme). You would also expect the vast majority of genotypes in close proximity to each other to inhabit extremely diverse regions of phenotype space. In this way, the tendrils of these genotype networks are both extremely disconnected from each other while also being tightly interwoven.
Extensions
Larger codon size
Borrowing two terms from biology: a nucleotide is what Typogenetics calls a base, and a codon is the group of nucleotides that codes for a single amino acid, which makes the duplets from earlier codons of size two. If a codon is composed of two nucleotides, then a single base can be translated into two different amino acids depending on the initial binding site. A codon of three nucleotides allows for three distinct meanings that a single base takes on, effectively increasing the density of genes without increasing the length of a strand. There may be a very good reason living systems on Earth use a codon of size three. I would be interested to explore the effects of codons of size 4, 5, or 6. The size of the instruction set need not increase to accommodate an increased number of possible codons. Just as in real biology, a large diversity of nucleotide combinations can be mapped to a smaller set of amino acids with redundancy built in. Would increasing the density of genetic information on a strand help us evolve complex systems faster?
More nucleobases
In real biology we have pyrimidines and purines. I would be curious to add a third category of bases. If I had to guess, A, C, G, T is close to the only code that satisfies both requirements of simplicity and error correction. Simplicity is a requirement because anything more complex would have been vanishingly unlikely to evolve out of primordial metabolic networks. And error correction, of course, to ensure genetic code would be stable enough to propagate over time. However, we could have had a true binary code, which makes me wonder what the effect would be of a hexadecimal code. Does increasing the number of available nucleotides increase the expressive power?
Complex instruction set
The instruction set of 15 amino acids that Hofstadter gives us is certainly not the simplest possible instruction set, though there's something very beautiful about it being as reduced as it is. One does wonder how powerful strand rewriting could be with a few more instructions. I also wonder if the conditional rules that come in the box are a bit too complex. We currently can scan left/right until reaching a pyrimidine/purine. These are conditionals, but not as simple as "if purine, move left one unit" (think Brainfuck). Perhaps conditionals that simple could facilitate the evolution of more stable enzymes even if the enzymes need to be longer to do anything useful.
Wrapping up
I hope you enjoyed some of the visuals in this post and I hope you're as inspired by the joint simplicity and power of Typogenetics as I am.
: Douglas R. Hofstadter, Gödel, Escher, Bach: An Eternal Golden Braid (Basic Books, 1979). Typogenetics is introduced in Chapter XVI, "Self-Rep and Self-Rep".
: Edit (Aug. 2026): I came across "Computational Life: How Well-formed, Self-replicating Programs Emerge from Simple Interaction" by Blaise Agüera y Arcas and colleagues (2024), which is very relevant to open-ended search for interesting programs. They find that self-replicators arise from random interactions between programs with no explicit fitness function at all.
: Robert Axelrod and William D. Hamilton, "The Evolution of Cooperation", Science 211(4489), 1981, 1390–1396.
: Martin A. Nowak and Robert M. May, "Evolutionary Games and Spatial Chaos", Nature 359(6398), 1992, 826–829.
: John Horton Conway, interviewed by Numberphile. The quote begins around 4:50.
: Andreas Wagner, Arrival of the Fittest: Solving Evolution's Greatest Puzzle (Current, 2014).
: If you want the mental image, I think of Wagner's networks as the Windows 3D Pipes screensaver. There's a browser demo and Raymond Chen wrote up its history. Pipes of different colors (different enzyme functions) can be very close together (similar genotype).