Day 1 part 2 was harder than is common for the first day.
I ended up using parser combinators (attoparsec for Haskell), which morally feels like the "right" way to do this (so you don't have to manually keep track of how much you've read or somehow abuse regex lookaheads), but I don't know the library well and it took me some time to implement it correctly.