Fearless Debugging

2021-01-02Comments

Jurassic Jigsaw

My thanks to Eric Wastl for another excellent Advent of Code. I’ve now worked through all 25 puzzles, some simple, some tough, some familiar, some new; all beautifully set and highly enjoyable.

Day 20, Jurrasic Jigsaw, took me longest by far to complete. The puzzle is easy to understand. You have to assemble jigsaw pieces into a seascape. For part one, you need to find the corner pieces. For part two, you must locate monsters in the seascape.

Here, a jigsaw piece is a monochrome square, represented like so:

..##.#..#.
##..#.....
#...##..#.
####.#...#
##.##.###.
##...#.###
.#.#.#..##
..#....#..
###...#.#.
..###..###

And this is the sea monster:

                   # 
#    ##    ##    ###
 #  #  #  #  #  #

The twist was that the jigsaw pieces could be rotated and flipped over before matching them up. Once matched, the edges of the pieces were to be removed. Implementing the rotate, flip, match and remove code proved fiddly, and I was pleased to get this working and producing correct results for the supplied example.

Unfortunately my code produced the wrong answer for part two, the bit where you have to locate sea monsters. So, I would need to debug.

Fear of Debugging

Like it or not, debugging is a key part of software development.

Generally, I do like it. There’s satisfaction to be had in paring scope, retracing steps, then making the right fix, improving test coverage, and generally leaving the world a better place.

What I don’t like, though — what scares me — is the suspicion the bug lurks in the worst possible place. What if it’s in a library we don’t have the source for? Or if it’s a timing issue caused by some erratic locking? Or if there’s an issue with the compiler for the most obscure platform. Or, in this particular case, that the code to fiddle with jigsaw pieces has a bug — a bug subtle enough to pass the examples but fail the real thing.

It’s not unreasonable to fear the worst. At some point the issues mentioned above will cause bugs, bugs which are hard to fix. We need to be ready.

Fear, though, is the wrong mindset. Debugging requires you to be calm, methodical and detached. Much as an artist draws what they see and not what they know, a programmer must observe and follow the evidence. A second pair of eyes is always useful; simply explaining the issue to a colleague gives you another perspective.

Here be Monsters

I was working on my own on the Advent of Code. I could have tried explaining to a rubber duck, but didn’t. Instead I examined and traced my code. I checked and double-checked the flip, rotate, match and remove logic. I printed out intermediate state. I walked to the sea-front and back. I slept on it.

Fearing the worst turned out to be the wrong strategy.

What did work was reading the problem statement again, carefully. At last I saw it! Somehow, a rogue character had wormed its way into my inputs. The sea monster I had used looked like this:

                   #
#    ##    ##    ###
 #  #  #  #  #  #

when it should have been:

                  # 
#    ##    ##    ###
 #  #  #  #  #  #

Since both monsters appear the same number of times in the example seascape, my test case failed to catch the bug.

So, with a single, simple, whitespace correction, my advent of code was complete. One of life’s ironies is that when you lose something you find it in the last place you look. It’s not always so with debugging: a bug can exist in many different places and sometimes the fix causes the codebase to unravel, requiring a chain of additional fixes, but, in this case, finding the bug fixed it.

Seascape with monsters

A monster can exist in many different places, and in this case finding the monster fixed it