Day 4 was the first time I attempted to actually compete, for time, in the Advent of Code contest. I didn't do that well — it took me over 6 minutes to complete part A, which gave me a rank of 2181. I did much better on part B, with a total time just over 7 minutes and a rank of 1248. Read on to the end to see some ways I hope to improve in future challenges.
But first, how to tackle this one? Each input line in this challenge consists of two numeric intervals, like "2-4,6-8". For Part A, we need to report whether either span contains the other. My final code looks like this:
f = file.open("day4-input.txt")
total = 0
while true
line = f.readLine
if line == null then break // end of file
parts = line.split(",")
aFrom = parts[0].split("-")[0].val
aTo = parts[0].split("-")[1].val
bFrom = parts[1].split("-")[0].val
bTo = parts[1].split("-")[1].val
contained = (bFrom >= aFrom and bTo <= aTo) or
(aFrom >= bFrom and aTo <= bTo)
print aFrom + "-" + aTo + " vs " + bFrom + "-" + bTo + ": " + contained
total = total + contained
end while
print "total: " + total
As on previous days, I was doing this in command-line MiniScript. So to parse out the line, I first split
it on a comma, and then split each of those parts on the minus sign, finally applying val
to convert those strings to numbers. (This is one place I'll improve — see below.)
Then, checking whether one span contains another is just a matter of carefully comparing those four values. In my rush, I got this wrong, twice. Ouch. That cost me valuable time, and is why part A took so long.
For part B, we only had to count the lines where the two spans overlap. This is considerably easier, and something I was already comfortable with, because it's exactly the same thing you do (for each axis) when checking whether two rectangles overlap. The last three lines within the loop changed to:
overlap = bFrom <= aTo and bTo >= aFrom
print aFrom + "-" + aTo + " vs " + bFrom + "-" + bTo + ": " + overlap
total = total + overlap
...and the rest of the code stayed the same. (I got this one right on the first try, and it took under a minute.)
Future Plans
I'm having a blast solving these challenges with MiniScript, but I'd really like to get into the top 1000. So I need a bit more prewritten code to have my back. So tonight I'm going to do a couple things differently:
I'm going to copy the example data each challenge provides and run my code on that first, comparing my answers to the example answers. This should catch most of the dumb mistakes I might make, and avoid the wasted time of submitting a wrong answer. While it certainly takes a few extra seconds to do, I'm hoping it will be worth it overall.
-
I'm going to use Mini Micro instead of command-line MiniScript. Mini Micro has an extensive library of generally useful functions in /sys/lib. For example, by importing the stringUtil module, we get a
string.match
function that would have let me parse the input line out by doing:
m = line.match("{s1}-{e1},{s2}-{e2}")
and then referencing the values as
m.s1
, etc. I'm supplementing the standard libraries with some additional functionality that I hope will be useful. For example, I've written a
Span
class that represents a numeric interval, and supports all the functions I can think of to do with such things. That includes methods likecontains
andoverlaps
, which would have been helpful last night!
I'm sure there will be many nights when I say "Doh! I wish I had generic code that does this!" But hopefully there will be at least a few nights where I say "Aha! I have generic code that does this!" And by leveraging that code, I will be both faster and less likely to make mistakes.
If you want to join me, please do! I'm posting all the code on GitHub, including my little lib/aoc module. I encourage you to join us on Discord too, where we can strategize and commiserate. See you there!