5 | import Data.SortedMap
6 | import Control.Monad.State
7 | import Control.Monad.Identity
12 | ListHead : Type -> Type
13 | ListHead a = Lazy (List a) -> List a
16 | (<::>) : Lazy (ListHead a) -> Lazy (ListHead a) -> ListHead a
17 | xs <::> ys = (\x => xs (ys x))
20 | Input = List Integer
22 | parseInput : String -> Maybe Input
24 | traverse parsePositive . map trim . forget . split (== ' ') . trim $
str
26 | digitCount : Integer -> Integer
27 | digitCount i = digitCount' i 1
29 | digitCount' : (i, acc : Integer) -> Integer
33 | else digitCount' (i `div` 10) (acc + 1)
35 | splitDigits : Integer -> Maybe (Integer, Integer)
37 | if (digitCount i `mod` 2) == 0
39 | let new_len = integerToNat $
(digitCount i) `div` 2
40 | diver = natToInteger $
10 `power` new_len
41 | in Just (i `div` diver, i `mod` diver)
45 | blinkStone : (stone : Integer) -> (times : Nat)
46 | -> State (SortedMap (Integer, Nat) Nat) Nat
47 | blinkStone stone 0 = pure 1
48 | blinkStone stone (S times) = do
50 | case lookup (stone, (S times)) cache of
55 | rest <- blinkStone 1 times
56 | modify $
insert (stone, (S times)) rest
58 | else case splitDigits stone of
60 | rest_1 <- blinkStone x times
61 | rest_2 <- blinkStone y times
62 | modify $
insert (stone, (S times)) (rest_1 + rest_2)
63 | pure (rest_1 + rest_2)
65 | rest <- blinkStone (stone * 2024) times
66 | modify $
insert (stone, (S times)) rest
70 | countStones : (stones : List Integer) -> (times : Nat)
71 | -> State (SortedMap (Integer, Nat) Nat) Nat
72 | countStones stones times = do
73 | xs <- traverse (\x => blinkStone x times) stones
77 | part1 : String -> IO (String, Input)
79 | Just input <- pure $
parseInput str
81 | let (_, count) = runState empty (countStones input 25)
82 | pure (show count, input)
85 | part2 : Input -> String -> IO String
87 | let (_, count) = runState empty (countStones input 75)