52 lines
1.3 KiB
Haskell
Raw Normal View History

2025-12-05 12:56:40 +00:00
module Puzzles.Day5 (puzzle) where
2025-12-08 12:48:49 +00:00
import Pre
2025-12-05 12:56:40 +00:00
puzzle :: Puzzle
puzzle =
Puzzle
{ number = 5
, parser = const do
ranges <- (Range <$> decimal <* single '-' <*> decimal) `sepEndBy` newline
2025-12-05 13:16:33 +00:00
void newline
vals <- decimal `sepEndBy` newline
2025-12-05 13:16:33 +00:00
pure (ranges, vals)
2025-12-05 12:56:40 +00:00
, parts =
( \(ranges, vals) ->
length
2025-12-05 14:39:42 +00:00
. filter (flip any ranges . isInRange)
$ vals
)
/\ ( sum
. map rangeLength
. foldr addInterval []
. sortOn (Down . (.lower))
. fst
)
/\ nil
2025-12-05 12:56:40 +00:00
, extraTests = mempty
}
2025-12-05 13:16:33 +00:00
data Range = Range
{ lower :: Int
, upper :: Int
}
deriving (Eq, Ord, Show)
2025-12-05 15:36:12 +00:00
rangeLength :: Range -> Int
rangeLength r = r.upper - r.lower + 1
2025-12-05 13:16:33 +00:00
isInRange :: Int -> Range -> Bool
isInRange n r = n >= r.lower && n <= r.upper
2025-12-05 15:36:12 +00:00
extend :: Int -> Range -> Range
extend upper r = r{upper = max r.upper upper}
addInterval :: Range -> [Range] -> [Range]
addInterval new = \case
[] -> [new]
(r : rs) ->
if isInRange new.lower r
then extend new.upper r : rs
else new : r : rs