diff --git a/README.md b/README.md index 133c3e1..15f9a82 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,4 @@ Development occurs in language-specific directories: |[Day8.hs](hs/src/Day8.hs)|[Day8.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day8.kt)|[day8.py](py/aoc2024/day8.py)|[day8.rs](rs/src/day8.rs)| |[Day9.hs](hs/src/Day9.hs)|[Day9.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day9.kt)|[day9.py](py/aoc2024/day9.py)|[day9.rs](rs/src/day9.rs)| |[Day10.hs](hs/src/Day10.hs)|[Day10.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day10.kt)|[day10.py](py/aoc2024/day10.py)|[day10.rs](rs/src/day10.rs)| +|[Day11.hs](hs/src/Day11.hs)|||| diff --git a/hs/aoc2024.cabal b/hs/aoc2024.cabal index 43acbfa..623493a 100644 --- a/hs/aoc2024.cabal +++ b/hs/aoc2024.cabal @@ -23,6 +23,7 @@ library exposed-modules: Day1 Day10 + Day11 Day2 Day3 Day4 @@ -71,6 +72,7 @@ test-suite aoc2024-test main-is: Main.hs other-modules: Day10Spec + Day11Spec Day1Spec Day2Spec Day3Spec diff --git a/hs/app/Main.hs b/hs/app/Main.hs index aff0848..cc49f4f 100644 --- a/hs/app/Main.hs +++ b/hs/app/Main.hs @@ -9,6 +9,7 @@ import Data.Text (Text) import Data.Text.IO qualified as TIO (readFile) import Day1 qualified (part1, part2) import Day10 qualified (part1, part2) +import Day11 qualified (part1, part2) import Day2 qualified (part1, part2) import Day3 qualified (part1, part2) import Day4 qualified (part1, part2) @@ -50,3 +51,4 @@ main = do run 8 print [Day8.part1, Day8.part2] run 9 print [Day9.part1, Day9.part2] run 10 print [Day10.part1, Day10.part2] + run 11 (either fail print) [Day11.part1, Day11.part2] diff --git a/hs/bench/Main.hs b/hs/bench/Main.hs index 61c34c2..aa8385a 100644 --- a/hs/bench/Main.hs +++ b/hs/bench/Main.hs @@ -8,6 +8,7 @@ import Data.Text (Text) import Data.Text.IO qualified as TIO (readFile) import Day1 qualified (part1, part2) import Day10 qualified (part1, part2) +import Day11 qualified (part1, part2) import Day2 qualified (part1, part2) import Day3 qualified (part1, part2) import Day4 qualified (part1, part2) @@ -92,5 +93,11 @@ main = "Day 10" [ bench "part 1" $ nf Day10.part1 input, bench "part 2" $ nf Day10.part2 input + ], + env (getDayInput 11) $ \input -> + bgroup + "Day 11" + [ bench "part 1" $ nf Day11.part1 input, + bench "part 2" $ nf Day11.part2 input ] ] diff --git a/hs/src/Day11.hs b/hs/src/Day11.hs new file mode 100644 index 0000000..0cd9ec3 --- /dev/null +++ b/hs/src/Day11.hs @@ -0,0 +1,31 @@ +{-# LANGUAGE MultiWayIf #-} + +-- | +-- Module: Day11 +-- Description: +module Day11 (part1, part2, solve) where + +import Common (readEntire) +import Data.IntMap (IntMap) +import Data.IntMap qualified as IntMap (toList) +import Data.IntMap.Strict qualified as IntMap (fromListWith) +import Data.Text (Text) +import Data.Text qualified as T (words) +import Data.Text.Read qualified as T (decimal) + +part1, part2 :: Text -> Either String Int +part1 = solve 25 +part2 = solve 75 + +solve :: Int -> Text -> Either String Int +solve n input = do + nums <- mapM (readEntire T.decimal) $ T.words input + pure $ foldl' (+) 0 $ iterate step (IntMap.fromListWith (+) $ (,1) <$> nums) !! n + +step :: IntMap Int -> IntMap Int +step counts = IntMap.fromListWith (+) $ do + (x, n) <- IntMap.toList counts + if + | x == 0 -> [(1, n)] + | s <- show x, (l, 0) <- length s `divMod` 2, (a, b) <- splitAt l s -> [(read a, n), (read b, n)] + | otherwise -> [(2024 * x, n)] diff --git a/hs/test/Day11Spec.hs b/hs/test/Day11Spec.hs new file mode 100644 index 0000000..b6d1d83 --- /dev/null +++ b/hs/test/Day11Spec.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Day11Spec (spec) where + +import Data.Text (Text) +import Day11 (solve) +import Test.Hspec (Spec, describe, it, shouldBe) + +example1, example2 :: Text +example1 = "0 1 10 99 999\n" +example2 = "125 17\n" + +spec :: Spec +spec = do + describe "part 1" $ do + it "examples" $ do + solve 1 example1 `shouldBe` Right 7 + solve 6 example2 `shouldBe` Right 22 + solve 25 example2 `shouldBe` Right 55312