
I knew it had to come someday: those puzzles where you run around on a character-based grid. Day 15 was one of those. I’m definitely not one of those people who just pull maze traversal algorithms out of thin air, and to learn them I read an overview of the algorithm and then try to implement is. And then start with the headache of why things aren’t working, or your robot just walks up and down along 2 coordinates, etc. etc.
So again I needed visualization to help me grok things. First try: keep it simple. Just use a whole bunch of print()
statements, and combined with some manual path programming I thought I was doing well. Haha Mr. Wastl, I defy your fiendish puzzle! I’ll just walk manually! I thought I was Mr. Smartypants for keeping things so simple, but I just had to keep walking… and walking… and… well.
def manual_route(): top_cap = '131143133131413131231231231231323242323132324232313' to_bottom = '23234234234234234234232424122323232323232324124223242424' right_cave = '143143143114142424242142424242424141413123123123231314131313232232323131131' finish_bottom = '313232323224231313131313413141441413413413141414242424242441414141141424141131313133131444' finish_top_left = '131331313323223232324432332322323112222424' backtrack = '3311441111441144222242444' explore_right = '41421421421421421421424141341341413131323233131331311414141314141414414141313313143143143143141' from_chimney = '31323131431431413131231231231232313131414141441411' t_split_left = '3131313131231231231323243234232424112224232424242424242223233232324244242342342424111122223323231' appendix = '232424331131331314431313131323233131331314131323131413131231232313131414141441413141424142342423232324242421141414141133' backtrack_to_t = '442233333311441133' going_up_from_t = '1113134331313413411' yet_another_t = '4141221133313123123123123132323242424242232342331312323131443331313232323423423423423423242' going_down_left = '414111222242423242412412421413344224242423232323323244323323232322232312312323131413133' route = top_cap + to_bottom + right_cave + finish_bottom + finish_top_left + backtrack + explore_right + from_chimney + t_split_left + appendix + backtrack_to_t + going_up_from_t + yet_another_t + going_down_left return route
Yes, I really was that dumb to go "3", Ctrl-R, "41", Ctrl-R, <Backspace>2, Ctrl-R… All the above was my manual exploration of the maze. I was sort of Zen, I admit 🙂
Soo… it was time for the real thing. A wall hugging algorithm and curses
. I prefer to use as few external libraries as I can, so I turned to the standard curses
module. This was slightly more complicated than my use of Pillow because Unix and history and terminals and other weirdness. Like every coordinate being in y, x
order. Because reasons.

There’s actually quite a lot of nifty things you can do with curses
, like windows and flashing characters, but I chose to keep it tightly coupled to puzzle solving. This means that you should just be able to pass in the puzzle’s coordinate system and projecting that onto the screen is done for you.
Another part is handling the initialization and teardown, which is a bit fiddly, but clearly explained in the docs. Because of this I chose to implement it as a ContextManager
by implementing the <strong>enter</strong>()
and <strong>exit</strong>()
methods. I really like how convenient the with...
syntax is.
curses
has a nice abstraction to deal with large areas that fall outside the projectable area, a pad
. This means we don’t have to worry about the screen size, we can call a refresh
() with parameters that allow us to specify which part of the pad
to display.
I’m pretty happy with how the convenience class turned out. Here’s a simple way to plot a bunch of points in a list.
bounds = CursesVisualizer.boundaries(list_of_points, padding=1) with CursesVisualizer(bounds) as cv: for point in list_of_points: cv.plot(point, '#') cv.refresh()
Have a look at the convenience class here: have fun cursing
!
Advent of Code 2019 Series
- Advent of Code 2019 Has Started – Join In!
- Advent of Code 2019 – Day 2
- Advent of Code: How Excel Made My Day and Saved My Son’s Day Too
- Advent of Code – Day 4: Visualize
- Advent of Code – Day 5: Saintaerkla2s
- Advent of Code – Day 6: How I Got Hooked on AoC
- Advent of Code – Day 7: Share Your Workflow
- Advent of Code – Day 8: How Simple Things Can Be Very Hard for Some People
- Advent of Code – Day 9: How I Started Enjoying Solving Programming Puzzles
- Advent of Code – Day 10: Space Cowboys Shooting Pixels in the Sky
- Advent of Code – Day 11: To Be or Not to Be
- Advent of Code – Day 12: Shooting for the Moon
- Advent of Code – Day 14: Chain Reaction
- Advent of Code – Day 16: Curses
- Advent of Code – Day 17: Vacuuming a Scaffold with the Intcode Program
- How Little Green Men Helped Me Solve a Puzzle
- Advent of Code – Day 20: A Little Bit of Revision
- Advent of Code – Day 21: It’s a Marathon, Not a Sprint
- Advent of Code – Day 22: Shuffling Cards Until Eternity
- Advent of Code – Day 23: The Network is Reliable
- Advent of Code – Day 24 & 25: Think Out of the Box