module Day5 where import Debug.Trace import Data.Char import Data.List import Util type Range = (Int,Int) parse :: String -> ([Range], [Int]) parse s = foldl addLine ([], []) $ map (map read) $ map (splitOn (not . isDigit)) $ lines s where addLine (ranges, queries) [lhs, rhs] = ((lhs, rhs) : ranges, queries) addLine (ranges, queries) [q] = (ranges, q : queries) addLine (ranges, queries) [] = (ranges, queries) inRange :: Range -> Int -> Bool inRange (lo,hi) q = lo <= q && q <= hi inRanges :: [Range] -> Int -> Bool inRanges rs q = any (\r -> inRange r q) rs part1 :: String -> String part1 input = let (rs,qs) = parse input in show $ length $ filter (inRanges rs) qs rangeUnion :: [Range] -> [Range] rangeUnion rs = let mergeWith cur [] = [cur] mergeWith (lo,hi) ((lo',hi') : rest) = if lo' <= hi then mergeWith (lo, max hi hi') rest else (lo, hi) : mergeWith (lo', hi') rest merge [] = [] merge (r : rest) = mergeWith r rest in merge $ sort rs part2 :: String -> String part2 input = let (rs, _) = parse input in show $ sum $ map (\(a,b) -> b-a+1) $ rangeUnion rs