module Day11b

import Prelude
import Node
import Aoc
import SortedMap

-- Alternate version that doesn't use string

infixl 7 _%_
pfunc _%_ : Int → Int → Int := `(x,y) => x % y`

-- 32 bit ints are too small
pfunc div53 : Int → Int → Int := `(x,y) => Math.floor(x / y)`

stone : Int → Either Int (Int × Int)
stone num = if num == 0 then Left 1 else go num num 1
  where
    go : Int → Int → Int → Either Int (Int × Int)
    go a b mod =
      if b == 0 then Right (a, num % mod)
      else if b < 10 then Left (2024 * num)
      else go (div53 a 10) (div53 b 100) (mod * 10)

step : List (Int × Int) → List (Int × Int)
step xs = go Nil xs
  where
    go : List (Int × Int) → List (Int × Int) → List (Int × Int)
    go acc Nil = acc
    go acc ((x,c) :: xs) = case stone x of
      Left a => go ((a,c) :: acc) xs
      Right (a,b) => go ((a,c) :: (b,c) :: acc) xs

iter : Int → SortedMap Int Int → Int
iter count parts = let x = go count parts in foldl _+_ 0 $ map snd $ toList x
  where
    go : Int → SortedMap Int Int → SortedMap Int Int
    go 0 stuff = stuff
    go x stuff = go (x - 1) $ foldMap _+_ EmptyMap $ step $ toList stuff

run : String -> IO Unit
run fn = do
  putStrLn fn
  text <- readFile fn
  let stuff = foldMap _+_ EmptyMap $ map (\ x => (stringToInt x, 1)) $ split (trim text) " "
  let p1 = iter 25 stuff
  putStrLn $ "part1 " ++ show p1
  let p2 = iter 75 stuff
  putStrLn $ "part2 " ++ show p2

main : IO Unit
main = do
  run "aoc2024/day11/eg.txt"
  run "aoc2024/day11/input.txt"
