Not sure how I feel about this one. I don't mind a "day off" of sorts, but there were just so. many. words in the puzzle that boiled down to such a straightforward implementation. I guess this is practice of "implement detailed requirements exactly to spec" or something.
Part 1 was my own, but was far, far too slow for part 2. I couldn't find a way to optimize it and didn't want to get stuck on the day forever, so I cribbed a solution from a Reddit post explaining a much faster way to solve it.
This adds constants for box-type-drawing characters and expands the logger's support for printing colored chunks without needing a newline. The result is quite nice! Credit to r/adventofcode for the idea :)
I...I know there's a way to map all the ranges together to build intersections and make a smart decision about this, but I just...don't really want to do that. This brute force approach finishes in about 55 seconds in Debug and 5 seconds in Release on my PC in a single thread, which...is fine. For now.
This moves all the actual handling to the parse function (so that part 2 can run on its own instead of requiring part 1 to fill its data structure for it). Now each part is just operating on the segment of the parsed data that is appropriate to it, and we can much more efficiently handle gears as we come across numbers instead of trying to search for numbers after finding a gear.