Poople

How We Built a Daily Word Ladder Game: The Graph Behind Poople

An engineering deep dive into how Poople works: the word ladder graph, the BFS-precomputed par, the runtime solver, and the daily puzzle math.

Poople Team10 min
The word graph behind Poople, four-letter words connected one letter apart

Poople is a daily word ladder game: change a four-letter word into POOP one letter at a time, with every step a real word. Poople looks like a simple word game on screen, but underneath it is a graph problem, and solving one well is an exercise in breadth-first search. This post walks through the word ladder algorithm behind the game: how the word graph is built, how every puzzle’s par is precomputed, how the runtime solver finds a shortest path in a handful of steps, and how the same puzzle reaches every player in the world without a server. If you are new to word ladders, start here for the rules and a few worked examples.

A Word Ladder Is a Graph Problem

Every four-letter word in the dictionary is a node. Two nodes get an edge between them if the two words differ by exactly one letter: CORD and CARD are connected, because swapping a single letter turns one into the other, while CORD and WARM are not, because getting from one to the other takes three separate one-letter swaps. Build that structure across the entire dictionary, all 2,398 four-letter words, and it forms a single connected word graph: every word connects to POOP through some chain of one-letter moves. Playing a word ladder puzzle is walking that graph one edge at a time, and solving it well is finding the shortest path through it.

Once a word ladder looks like a graph, it stops looking like a wordplay trick and starts looking like a pathfinding problem, the same shape as the classic LeetCode Word Ladder problem that shows up in technical interviews. That overlap is worth its own post, but the short version is that both problems reduce to finding the shortest path between two nodes in an unweighted graph.

The Poople word graph, four-letter words as nodes connected by one-letter-apart edges

Every Poople puzzle reports a par: the fewest possible steps from the day’s start word to POOP. Par is what turns a word ladder from an open-ended puzzle into something a player can score themselves against, and it only means anything if the number is exact. Guessing at a fair value is not good enough, so the game computes it with breadth-first search.

The idea is to run BFS once, offline, starting from POOP instead of from any particular start word. BFS expands outward from POOP one layer at a time: first every word one letter away from POOP, then every word one letter away from those, and so on, recording the first time it reaches each word, which becomes that word’s shortest distance back to POOP. POOP itself sits at distance 0. Because BFS explores layer by layer rather than following one path at a time, the first time it touches any word is guaranteed to be by the shortest possible route, which is exactly the par value the game needs.

Breadth-first search rippling out from POOP in layers to precompute par distances

Across the full dictionary, that search produces distances from 0 to 11. Three words sit at the maximum: AUGH, INCH, and UMPH are each 11 steps from POOP by the shortest possible route, the hardest starting points in the entire game. Running this BFS is the only expensive step in the whole system, and it happens once, offline, long before anyone opens the game. The result is a distance table that ships with the game as plain data. At play time, looking up a word’s par is a single map lookup, not a graph search: the browser never runs BFS to show a par value, it just reads one out of a table that was already computed.

The Runtime Word Ladder Algorithm: Greedy Descent

Par tells a player how many steps a shortest path takes, but the game also needs to produce an actual path, for hints and for checking a player’s progress against the best possible route. That is a different problem from looking up a number, and it runs a different algorithm at runtime: greedy descent through the par table.

From the current word, the solver looks at every neighbor, every word that differs from it by exactly one letter, and steps to any neighbor whose par is exactly one less than the current word’s par. Repeat that from the new word, and the par count ticks down by one at every step until it hits zero at POOP.

Finding those neighbors is cheap. A four-letter word has four letter positions, and each position can be swapped for any of 26 letters, so there are at most 4 times 26, or 104, candidate strings to check at each step. Each candidate is tested against a set of real words in constant time, so the whole step costs O(word length times 26), independent of how large the dictionary is.

This greedy approach always finds a shortest path, and the guarantee comes directly from how BFS built the par table in the first place. BFS layering guarantees that every word at distance d has at least one neighbor at distance d minus 1, the neighbor that pulled it into that layer during the original search. Greedy descent just retraces that structure one hop at a time, and every hop it needs is guaranteed to exist.

Finding Every Shortest Path

Greedy descent is enough to hint at one path, but the word ladder solver tool promises something bigger: every shortest path between any two four-letter words, not just one route. That needs a second, more thorough algorithm.

The all-shortest-paths solver still starts with a layer-by-layer BFS, but with one change: instead of recording a single predecessor for each word, it records the full set of parent words that reached it during the previous layer. A word can have several different neighbors at the layer just before it, and any one of those neighbors is a valid step on some shortest path, so the solver keeps all of them rather than picking one and discarding the rest.

Once that multi-parent map is built, reconstructing the actual paths means walking it backward from the target word to the start word, following every branch. The solver does that with an iterative depth-first search: an explicit stack holds the search state instead of function calls holding it, so there is no recursion and no risk of a stack overflow on a long or heavily branching ladder. The search pushes a partial path and its current word onto the stack, pops it, extends it by every parent recorded at that layer, and pushes the results back on, until it reaches the start word. To keep the output usable on a page rather than an unreadable wall of routes, the solver caps its results at 20 paths.

The Hidden Structure of the Word Graph

Building the word graph for gameplay also makes it possible to study the graph itself, and the connectivity turns out to be far from even. Some words sit at the center of dense clusters with dozens of one-letter neighbors, while others sit almost alone.

The best-connected words in the dictionary, the hub words, are PAPS, PATS, and WARE, each with 25 neighbors, meaning 25 other real words are exactly one letter swap away. CARE follows close behind with 24 neighbors, and a cluster of words including BOBS, CAPS, CARS, and CORE each have 23. Landing on a hub word mid-puzzle opens up a wide set of next moves, which is part of why some ladders feel easier than their par number suggests.

At the other extreme, 99 words in the dictionary are dead ends: each has exactly one neighbor, so there is only one legal move out of it. Land on a dead end that is not already on the path to POOP, and the only option is to backtrack.

The graph’s structure also breaks down by starting letter, and the gap is large. Words starting with U are the hardest on average, with a mean par of about 8.6 steps to POOP, while words starting with C are the easiest, averaging about 4.1 steps. That gap reflects how many real four-letter words share each starting letter and how densely those words connect to the rest of the graph. The strategy guide breaks down hub words, dead ends, and starting-letter difficulty in more detail, for players who want to use this structure while solving rather than just reading about it.

One Puzzle for the Whole World

Poople has no backend generating puzzles and no database picking a word for the day. The daily word ladder game is pure date math, computed the same way on every device.

The game defines a fixed epoch, 08:00 UTC on August 14, 2025, and computes today’s day number as the number of full 24-hour periods that have passed since that epoch: the floor of the elapsed time divided by 24 hours. Because the puzzle rolls over at 08:00 UTC, that day number changes at the same instant everywhere in the world, regardless of local time. The day number then maps to a start word by indexing modulo into a fixed pool of 1,137 start words, so day 0 picks one word, day 1 picks the next, and the sequence repeats only after the whole pool has been used.

There is no randomness anywhere in this calculation and nothing to synchronize over a network. Any two devices computing the same formula at the same moment land on the same day number and the same start word, which is what lets the same daily word puzzle reach every player in the world on any given day, without ever calling a server to ask.

Why Precompute?

Put together, these pieces reflect one architectural choice: do the expensive graph work once, offline, and ship the results as data. BFS from POOP runs a single time to build the par table, and the game never runs it again during play. At play time, checking a word’s par is an O(1) lookup, and only the hint solver, the standalone word ladder solver tool, and the tests that verify the precomputed table stays correct ever run graph search live. Treating the distance table as data rather than as code that runs on every page load keeps the game fast and simple to reason about, even though the underlying graph problem still takes real computation to solve.

Frequently Asked Questions

What algorithm does a word ladder use?

The core idea is to model every word as a node in a graph, connect words that differ by exactly one letter, and use breadth-first search to find the shortest path between two words. Poople precomputes those BFS distances ahead of time and stores them as each word’s par.

Is a word ladder a graph problem?

Yes. Each word is a node, and an edge connects two words that differ by exactly one letter. Solving a word ladder means finding a path through that graph from the start word to the target word, the same problem shape as the classic LeetCode Word Ladder problem.

How is Poople’s daily puzzle the same for everyone?

The day number comes from pure UTC date math measured from a fixed epoch, then maps to a start word by indexing modulo into a fixed pool of start words. There is no server and no randomness involved, so every player in the world gets the same puzzle on the same day.

Can I see the shortest path for any word ladder?

Yes. The word ladder solver lists every shortest path between any two four-letter words, not just one route, using the same word graph that powers the daily game.

Play Poople Today

Play today’s Poople and watch the par-based scoring in action, or warm up in Poople Unlimited for as many practice ladders as you want. To explore the word graph directly, the word ladder solver maps every shortest path between any two words. Poople is open source, so the code behind everything in this post is there to read for anyone curious enough to go looking.