Advent of Code 2025
1module Day5 where
2
3import Debug.Trace
4import Data.Char
5import Data.List
6import Util
7
8type Range = (Int,Int)
9
10parse :: String -> ([Range], [Int])
11parse s = foldl addLine ([], []) $ map (map read) $ map (splitOn (not . isDigit)) $ lines s
12 where addLine (ranges, queries) [lhs, rhs] = ((lhs, rhs) : ranges, queries)
13 addLine (ranges, queries) [q] = (ranges, q : queries)
14 addLine (ranges, queries) [] = (ranges, queries)
15
16inRange :: Range -> Int -> Bool
17inRange (lo,hi) q = lo <= q && q <= hi
18
19inRanges :: [Range] -> Int -> Bool
20inRanges rs q = any (\r -> inRange r q) rs
21
22part1 :: String -> String
23part1 input =
24 let (rs,qs) = parse input
25 in show $
26 length $
27 filter (inRanges rs) qs
28
29rangeUnion :: [Range] -> [Range]
30rangeUnion rs =
31 let mergeWith cur [] = [cur]
32 mergeWith (lo,hi) ((lo',hi') : rest) =
33 if lo' <= hi then
34 mergeWith (lo, max hi hi') rest
35 else
36 (lo, hi) : mergeWith (lo', hi') rest
37
38 merge [] = []
39 merge (r : rest) = mergeWith r rest
40 in merge $ sort rs
41
42part2 :: String -> String
43part2 input =
44 let (rs, _) = parse input
45 in show $
46 sum $
47 map (\(a,b) -> b-a+1) $
48 rangeUnion rs