Dig A Verse

Year: 2026
Medium: Creative Coding, Generative Poetry
Tools: Python, Tracery, p5.js, Jupyter
Role: Concept, Writing, Programming

A small machine that writes tiny dinosaur poems, somewhere between nonsense and tenderness.

G Z P Z Q F Q Q H Z A A L S N C E Z Y H H W B N X Y N T O B K R P W D U L A E X C D Z A O F R X
K M P E F V B P H C Y G G V Z V Y Y S X C D R P R M G K E R N J L O Q M K P M I A C F W W P A P
C R T X Q H S T K R T D F V F U L K L Y T J H D F C F Y N L F V B V Q V H N F X S A L P Q M V H
H F R C O Z N Y X P B J B I V J B N H F M C K U E E X X P B I E U Q X P A G L Z E L T Y N P S P
J E R S I E Y X A M V E W A I S K U H S N I V M Y Z E E E D M D F A U O Z E C D U J E J R K M P
T F F B R A V E L I T T L E R E X C R E P T A W A Y B E F O R E T H E D A W N F M G W X R Y B T
X Y B Z A M O C T H R O U G H T W I S T E D F E R N S A N D B O L D L Y M A R C H I N G O N M Y
F W H I W T K X B T H E F O R E S T S H O O K W I T H O N E T R E M E N D O U S R O A R H M E J
Q Z R P S D R T B A N D R E X F O R G O T E A C H S T E P H E T O O K B E F O R E Q T X K Q J J
W T Q Y R G C T K G L C K V N D C U C U Z Y O Q T A V U W O P Q Q M M C H A B V N B H I W S M X
N O Z H M M K P H U U C B P F P L W T G Y O U U Y T V X T W V I H P P M J T M Q W A F K G J M W
E C R F C Q J T M X X O D F W N G V K L U S V G I C A K Q I E V Q G H T W I W M F M O M N O T V
I V F V M T I D G G B L Z U W L A C Q S B M T O W O H A R E D J G O L A L F E S Z N Q B J G N M
R H H S Z S O Z A V S C C N X Y V G E B P Q T R T P P V Z V K E I E L J J U U A Z C V C F Q D V

Do an excavation to find the hidden T-rex adventure.

Reveal the poem

Brave Little Rex crept away before the dawn
through twisted ferns and boldly marching on
The forest shook with one tremendous roar
and Rex forgot each step he took before

Dino Poem is an extended study of children’s literature: a small system that writes short, rhyming poems about the adventures of a young T-rex — and then hides each finished poem inside a word-search puzzle.

Concept

The project grew out of an earlier assignment, where I tried to take apart the text of Peter Pan and build an algorithmic grammar for humor. It didn’t quite work — I realized I would first need to understand what actually makes a sentence funny, and that children’s literature isn’t always humorous anyway (the Grimm’s fairy tales I remember are pretty dark).

So I shifted my focus to children’s literature itself. Revisiting picture books I loved as a child — The Giving Tree, Dad, I Want the Moon, The Very Hungry Caterpillar — I noticed how much of their playfulness comes from short, rhyming sentences. I read about rhyme schemes (AABB and AABA) and Dr. Seuss, and decided a short rhyming poem would be a fun thing to generate.

Because this was a genre study, I didn’t want to import an existing text as a corpus. Instead I wrote the poems myself, around the subject that thrilled me most as a child: dinosaurs. Borrowing the narrative shape of Peter Rabbit, I wrote a short story-poem about a young T-rex slipping away on an adventure. Here is the very first one I wrote:

Mighty Little Rex crept past the gate one day
and deep into the Fern Forest made his way
Old Spinosaurus let out one great roar
and Rex’s legs moved faster than before

Process

The piece came together in two parts: a generator that writes the poems, and a puzzle that hides them.

Writing the generator. I gathered rhyming word pairs and wrote several interchangeable versions of each line, treating the poem’s four lines as four beats of the story. The T-rex’s name and the adjectives that describe it became their own swappable lists.

Building it in Tracery surfaced a problem: Tracery chooses each element independently, so a line ending in “day” was never guaranteed to land with a line ending in “way.” The rhymes kept breaking. The rhyming words also carried different meanings — some about time, some about place — so the lines had to stay matched in sense as well as in sound.

These are the rhyming pairs I settled on:

The fix was to pick a rhyming pair first, then slot it into lines written specifically to carry that pair’s meaning. A search pointed me toward nested dictionaries. The outer layer holds the swappable name and adj lists plus two groups of rhyme pairs — a_pairs for the first two lines, b_pairs for the last two:

rules = {
    "name": [...],
    "adj": [...],
    "a_pairs": [...],
    "b_pairs": [...],
}

Each pair is its own little dictionary that keeps the two rhyme words together with the candidate lines written to end on them:

"a_pairs": [
    {
        "a1": "day",
        "a2": "way",
        "line1": [...],   # candidate sentences ending in {A1}
        "line2": [...],
    },
    {
        "a1": "dawn",
        "a2": "on",
        "line1": [...],
        "line2": [...],
    },
]

From there, generate_poem() picks one a_pair and one b_pair at random, pulls one candidate line from each of the four slots, expands them with Tracery (filling in a random name and adjective), and finally substitutes the rhyme words back in at the line ends — so the rhyme is guaranteed every time.

Hiding it in a puzzle. While researching children’s literature I kept running into reading-and-writing games, and the word search caught my eye: it looked like a grid I could build by counting, which connected back to grid and pixel exercises from an earlier ICM class.

Thinking of the puzzle as a grid, I rebuilt that counting logic in Python. It wasn’t a direct port of my old p5.js sketches — in p5, x and y already mean a pixel’s position, but here i and j are just numbers, so I had to construct position and direction myself. With help from a classmate and more searching, I wrote functions that fill a row with random letters, and that hide one line of the poem at a random offset inside a row of noise. Stacking noise rows above and below the hidden lines turns the whole thing into a “find the poem” puzzle, with the answer printed underneath.

You can run the whole thing here — every press writes a new poem and buries it in a fresh grid:

Press “Generate” to build a fresh puzzle.

Reflection

For much of the semester I was fixated on making meaning out of messy text. From a filmmaking background, I work with script development and narrative prose regularly. I’m drawn to the unspoken parts of dialogue as much as the written ones, and I kept wondering whether the meaning buried in the unsaid could be coded at all.

Designing this Tracery rule convinced me that making meaning still takes a great deal of deliberate human input — you have to be very intentional about the “said” for the “unsaid” to come through. Tracery is good at holding a strict structure in place, which left me thinking about a question we kept returning to in class: whether meaning is an essential part of computational text.