This commit is contained in:
Samae 2024-12-21 22:44:59 +02:00
parent 51cb2314a8
commit 16a2a70f57
6 changed files with 96 additions and 6 deletions

3
.gitignore vendored
View file

@ -1,7 +1,8 @@
result*
*.cabal
dist-newstyle
*.eventlog
*.eventlog*
*.prof
*.dot
*.pdf
aoc24-debug.*

View file

@ -12,6 +12,7 @@ import Day7
import Day8
import Day9
import Day10
import Day11
main :: IO ()
main = do
@ -34,5 +35,7 @@ main = do
-- Day8.main
-- putStrLn "Day 9"
-- Day9.main
putStrLn "Day 10"
Day10.main
-- putStrLn "Day 10"
-- Day10.main
putStrLn "Day 11"
Day11.main

View file

@ -28,6 +28,7 @@
ghcid
cabal-install
fourmolu
eventlog2html
];
# Change the prompt to show that you are in a devShell
shellHook = ''

1
inputs/day11.input Normal file
View file

@ -0,0 +1 @@
5910927 0 1 47 261223 94788 545 7771

View file

@ -1,12 +1,13 @@
name: aoc24
ghc-options: -Wall -threaded
ghc-options: -Wall -threaded -O2
default-extensions:
- OverloadedStrings
dependencies:
- base == 4.*
- MemoTrie
- algebraic-graphs
- async
- attoparsec
@ -15,6 +16,7 @@ dependencies:
- hashable
- linear
- matrix
- mtl
- parallel
- recursion-schemes
- safe
@ -33,7 +35,7 @@ executables:
- aoc24
aoc24-debug:
main: Main.hs
ghc-options: -Wall -threaded -rtsopts -prof #-fprof-auto
ghc-options: -Wall -threaded -O2 -rtsopts -prof -auto-all #-fprof-auto
dependencies:
- aoc24
@ -50,7 +52,7 @@ library:
- Day8
- Day9
- Day10
# - Day11
- Day11
# - Day12
# - Day13
# - Day14

82
src/Day11.hs Normal file
View file

@ -0,0 +1,82 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
module Day11 where
import Control.Monad.State
import Data.Attoparsec.Text (Parser, decimal, parseOnly, sepBy)
import Data.Bifunctor (bimap)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as Map
import Data.Hashable (Hashable)
import qualified Data.Text.IO as T
parseInput :: Parser [Int]
parseInput = decimal `sepBy` " "
-- 1. If the stone is engraved with the number 0, it is replaced by a stone
-- engraved with the number 1.
-- 2. If the stone is engraved with a number that has an even number of digits,
-- it is replaced by two stones. The left half of the digits are engraved on
-- the new left stone, and the right half of the digits are engraved on the
-- new right stone. (The new numbers don't keep extra leading zeroes: 1000
-- would become stones 10 and 0.)
-- 3. If none of the other rules apply, the stone is replaced by a new stone; the
-- old stone's number multiplied by 2024 is engraved on the new stone.
applyRule :: Int -> Either Int (Int, Int)
applyRule 0 = Left 1
applyRule n | even leng = Right $ bimap read read $ splitAt half (show n)
where
half :: Int
half = leng `div` 2
leng :: Int
leng = length $ show n
applyRule n = Left $ n * 2024
solveA :: [Int] -> Int
solveA = sum . map (\x -> evalState (len 25 x) Map.empty)
-- borrowed from https://functional.computer/blog/memotries
memoize ::
(Eq a, Ord a, Hashable a, Eq c, Ord c, Hashable c) =>
(a -> c -> State (HashMap (a, c) b) b) ->
a ->
c ->
State (HashMap (a, c) b) b
memoize f counter val = do
computed <- get
case Map.lookup (counter, val) computed of
Just result ->
return result
Nothing -> do
result <- f counter val
modify $ Map.insert (counter, val) result
return result
len :: Int -> Int -> State (HashMap (Int, Int) Int) Int
len 0 _ = pure 1
len i n = case applyRule n of
Left v -> lenMemo (i - 1) v
-- trace (unwords [show i, "(", show n, "):", show v, "(", show u, ")"]) u
Right (v1, v2) -> do
u1 <- lenMemo (i - 1) v1
u2 <- lenMemo (i - 1) v2
pure (u1 + u2)
lenMemo :: Int -> Int -> State (HashMap (Int, Int) Int) Int
lenMemo = memoize len
solveB :: [Int] -> Int
solveB = sum . map (\x -> evalState (len 75 x) Map.empty)
inputEx :: [Int]
inputEx = [125, 17]
main :: IO ()
main = do
Right input <- parseOnly parseInput <$> T.readFile "inputs/day11.input"
putStrLn "Part 1"
print $ solveA inputEx
print $ solveA input
putStrLn "Part 2"
print $ solveB input