diff --git a/aoc2025.cabal b/aoc2025.cabal index fc5e794..dc6d7fb 100644 --- a/aoc2025.cabal +++ b/aoc2025.cabal @@ -49,3 +49,9 @@ executable day04 build-depends: , containers , libaoc + +executable day05 + import: common + hs-source-dirs: src + main-is: Day05.hs + build-depends: libaoc diff --git a/flake.nix b/flake.nix index 3fbca89..0d7db4b 100644 --- a/flake.nix +++ b/flake.nix @@ -45,7 +45,7 @@ name = n: "day${(if n < 10 then "0" else "") + toString n}"; in with pkgs.lib; - genAttrs (map name (range 1 4)) (n: { + genAttrs (map name (range 1 5)) (n: { type = "app"; program = "${self'.packages.aoc2025}/bin/${n}"; }); diff --git a/src/Day05.hs b/src/Day05.hs new file mode 100644 index 0000000..6ca5b3c --- /dev/null +++ b/src/Day05.hs @@ -0,0 +1,41 @@ +import qualified AoC as A (extract) +import Data.List (sort) +import Text.Parsec (char, digit, many1, newline, parse, sepEndBy, sepEndBy1) +import Text.Parsec.String (Parser) + +type Id = Int + +type Range = (Id, Id) + +parseInput :: Parser ([Range], [Id]) +parseInput = (,) <$> sepEndBy1 parseRange newline <* newline <*> sepEndBy parseId newline + where + parseRange :: Parser Range + parseRange = (,) <$> parseId <* char '-' <*> parseId + + parseId :: Parser Id + parseId = read <$> many1 digit + +part1 :: [Range] -> [Id] -> Int +part1 ranges = sum . map (fromEnum . fresh) + where + fresh :: Id -> Bool + fresh id = or [id >= a && id <= b | (a, b) <- ranges] + +part2 :: [Range] -> Int +part2 = + sum . map (\(l, r) -> r - l + 1) . foldr step [] . sort + where + step :: Range -> [Range] -> [Range] + step lst [] = [lst] + step (l1, r1) acc@((l2, r2) : xs) + | r1 < l2 = (l1, r1) : acc + | otherwise = (l1, max r1 r2) : xs + +main :: IO () +main = + do + raw <- readFile "./inputs/day5.in" + let (ranges, ids) = A.extract $ parse parseInput "" raw + putStr "Part 1: " >> print (part1 ranges ids) + putStr "Part 2: " >> print (part2 ranges)