Today in Advent of Code, we’re counting various interval relationships.
This post is literate Haskell, so here’s the traditional imports header:
import Control.Applicative (liftA2)
import Control.Category ((>>>))
import Data.List.Split (wordsBy)
import Numeric.Interval (Interval,(...),contains,intersection,isSubsetOf,null)
import Prelude hiding (null)
Since there’s really not much thinking involved in doing the interval relationship part, let’s spend some quality time parsing.
main :: IO ()
= interact $ main
First, split by lines.
lines >>>
On each line, extract the intervals.
map (wordsBy (== ',')) >>>
For each interval, split the lower and upper bound.
map . map) (wordsBy (== '-')) >>> (
Parse the bounds as integers. (No need to actually specify “integer” anywhere, the types are inferred. What’s not is that we’re actually converting.)
map . map . map) read >>> (
Convert the bound pairs to actual Interval
s.
map . map) (uncurry (...) . listToPair) >>> (
Perform the same kind of functional hackery we did on day 1 to compute both parts using the same pipeline.
flip countIf >>>
flip map [part1,part2] >>>
show
Both parts have the same core: count the number of interval pairs who are in a certain relationship, so that much was factored. Now the actual specificities.
part2 :: (Interval Int,Interval Int) -> Bool part1,
In part 1, we’re looking for intervals pairs where one contains the other. There are multiple ways to do this; here’s one.
= liftA2 (||) (uncurry contains) (uncurry isSubsetOf) part1
In part 2, we’re looking for intersecting intervals. I couldn’t find a function to do directly this in the library I’m using, but it’s simple enough to reproduce.
= not . null . uncurry intersection part2
For completeness, a couple of helper functions.
listToPair :: [a] -> (a,a)
= (a,b)
listToPair [a,b]
countIf :: ((a,a) -> Bool) -> [[a]] -> Int
= filter (listToPair >>> p) >>> length countIf p
This concludes today’s puzzle. I’m sorry I had to spice it up with pointless twiddling, I’m sure the following days will be more interesting. See you then!