It started, as most good arguments do, at the family table. A confident family member claimed to have won this solitaire game "several times" and found it "boring." With 40-plus years of playing this game and a background in quantitative analysis, the gauntlet was thrown.
The mission: simulate the game hundreds of millions of times and prove just how extraordinary — or ordinary — a win truly is.
The answer, after 700 million simulated games across Python and Julia implementations: not a single win. Zero. The game's name, passed down through generations, turns out to be an understatement. It's not once in a lifetime. It's once in a geological epoch.
This page tells the story of the game, the math, and the computational experiment that settled a family debate forever.
"The best part about a 1-in-700-million chance? It's not zero."
— The family motto, undefeatedStart with a standard 52-card deck, shuffled. Your goal: consolidate all 52 cards into a single stack. The rules are deceptively simple.
Draw cards one at a time and place them in a row of stacks, left to right.
Each new card can match with exactly two positions: the adjacent stack (immediately to its left) or the skip-two stack (with exactly two stacks between them). Think of it as: X X for adjacent, or X _ _ X for the far match. No other positions are ever checked.
Two cards match if they share the same suit or same rank. When matched, the new card goes on top of the matched stack, consolidating them.
After any match, cascading matches may occur — check if stacks can now match with their own adjacent or skip-two neighbors. Keep cascading until no more matches exist.
If neither position matches, the card starts a new stack to the right. Continue until all 52 cards are drawn. Fewer stacks = better.
A new card can only ever look at two places. Here they are, shown from the new card's perspective:
These are the only two positions ever examined. The stacks in between (dimmed above) are irrelevant to the matching decision. If neither position matches, the card starts a new stack.
You have four stacks on the table and draw A♠. The new card sits at position 5:
Result: A♠ lands on the 5♠ stack (pos 2). They share a suit. The table now has 3 stacks instead of 4. Then we check for cascades.
| Final Stacks | Achievement | Frequency | Rarity |
|---|---|---|---|
| 1 stack | ONCE IN A LIFETIME | 0 in 700M | Astronomically rare |
| 2 stacks | Legendary | 0.18% | ~1 in 550 games |
| 3 stacks | Exceptional | 13.3% | ~1 in 8 games |
| 4 stacks | Great game | 46.5% | Most common outcome |
| 5 stacks | Good game | 31.7% | Typical |
| 6+ stacks | Keep trying | 8.3% | Below average |
The median game ends with 4 stacks. Getting to 3 is a good night. Getting to 2 is a story you tell people. Getting to 1 is something nobody has ever seen — not in 700 million tries.
A standard deck has 52! possible arrangements — that's 8.07 × 1067 unique shuffles. The game's position rule (adjacent or skip-two only) creates an extraordinarily constrained state space where winning requires a precise cascade of matches across all 52 cards.
Five compounding factors make the game nearly impossible:
Restrictive position rules. Only 2 of potentially dozens of stacks are ever checked — adjacent and skip-two. Most cards land with no valid match at all.
Sequential dependencies. Card order matters enormously. A winning sequence requires dozens of rare events in exact succession.
Choice constraints. When both positions match, picking one eliminates the other permanently.
Cascade fragility. Chain reactions can consolidate stacks dramatically — but they require multiple stacks to align by suit or rank in precisely the right positions.
Convergence requirements. Going from 4 stacks to 3 is a 13% event. Going from 3 to 2 is 0.18%. Going from 2 to 1 has never been observed. Each step is exponentially harder than the last.
| Implementation | Language | Speed | Matching Logic |
|---|---|---|---|
| OnceInALifetime.jl | Julia | ~240,000 games/sec | Correct: adjacent + skip-two only |
| GoodOne2.py | Python | ~35,000 games/sec | Correct: adjacent + skip-two only |
| OiaLver0.0.5.py | Python | ~35,000 games/sec | Bug: checks all 3 positions within range* |
*Implementation note: OiaLver0.0.5.py has a bug on line 39 — its range(max(0, index-3), index) checks all positions within 3 (including the illegal 2-back position), making the game slightly easier than the real rules. The 700M simulation results are valid because they used the Julia implementation (OnceInALifetime.jl) and GoodOne2.py, both of which correctly enforce adjacent-only and skip-two-only matching.
"A family member claimed to have won several times and found it boring. 700 million simulations later, we can confidently say: no, you didn't."
— The conclusion, backed by mathThis game has been played at family gatherings for decades. It teaches patience, probability intuition, and the humbling experience of attempting something genuinely, mathematically near-impossible. Every game is a fresh chance — not to win, but to see how close you can get.
The code is open source. Try it yourself: github.com/pem725/OnceInALifetime