CognitoCoding All posts
3 July 2026 3 min read by Eris Taylor

I Wrote a Bubble Sort to Harvest Cactus — And Then It Crashed at the Boundary

pythonbubble-sortminecraftalgorithmsfarmer-ai

The Problem You Didn't Know Was a Sorting Problem

Zero's Farmer AI series — building an automated cactus farm in Minecraft using actual code — hit a wall in episode 6. Not a literal wall. A boundary crash.

The farm needed to decide which cactus to harvest next. Simple enough, right? Except "which one next" is a sorting problem. And sorting problems, when they go wrong, crash at the edges.


What Is Bubble Sort?

Bubble sort is one of the oldest, simplest sorting methods. The name comes from the way it works: bigger values "bubble" to the top, one swap at a time.

Here's the core idea. You look at two items next to each other. If they're in the wrong order, swap them. Move on to the next pair. Repeat. Keep doing this until you get through a full pass without making any swaps — that means everything's in order.

In Python, it looks like this:

def bubble_sort(items):
    n = len(items)
    for i in range(n):
        for j in range(n - 1):
            if items[j] > items[j + 1]:
                items[j], items[j + 1] = items[j + 1], items[j]
    return items

Simple. Readable. Works — until it doesn't.


Why It's Perfect for a Cactus Farm

The farm tracks each cactus: how tall it is, when it last grew, which column it's in. To decide what to harvest next, you want the tallest ones at the front of the list.

That's bubble sort. Score each cactus, sort the list highest to lowest, harvest from the top.

Except it crashed.


The Boundary Bug

Here's the inner loop that blew up:

for j in range(n - 1):
    if items[j] > items[j + 1]:
        ...

Looks fine. range(n - 1) means j goes from 0 to n - 2. And items[j + 1] at the last step is items[n - 1] — the final item in the list. Still in bounds.

So why did it crash?

Because the outer loop runs n times — even after the later positions are already in their final, sorted place. On later passes, the code kept comparing tail positions that didn't need checking, and when the list had been updated mid-run by the farm's data feed, it found nothing where it expected something.

The fix: shrink the inner loop on each outer pass. After every full sweep, the largest unsorted item is guaranteed to be sitting in its final position. You don't need to touch it again.

def bubble_sort(items):
    n = len(items)
    for i in range(n):
        for j in range(n - 1 - i):  # shrink the window by one each pass
            if items[j] > items[j + 1]:
                items[j], items[j + 1] = items[j + 1], items[j]
    return items

That one change — n - 1 becomes n - 1 - i — stops the crash and makes the sort faster. Each pass does less unnecessary work at the tail.


What This Actually Teaches

The bug lived at the boundary. The boundary is always where off-by-one errors hide.

Off-by-one means you're checking one position too many, or one too few. It's one of the most common mistakes in programming — at every level, from beginners to experienced developers. The reason it's so common is that it often looks right. The code reads correctly. The logic seems sound. But the edge case — the last item, the first item, the empty list — is where the assumption breaks.

The only way to find this bug was to run the code on real data. A cactus farm with varying heights and a live data feed, not a clean textbook array of five numbers.

That's the whole point of the Farmer AI series. Real problems break code in real ways. And when the code breaks, you learn something you wouldn't have learned from a worked example.


Watch the Full Episode

Episode 6 of I Taught an AI to Farm is live now. Zero walks through the cactus sorting problem from scratch — including the crash, the diagnosis, and the fix — all in real time.

Watch on YouTube →