module Day4 import Prelude import Node Round : U Round = List Int × List Int parseRound : String → Maybe Round parseRound s = let (a :: b :: Nil) = split s ": " | _ => Nothing in let (l :: r :: Nil) = split b " | " | _ => Nothing in Just (nums l, nums r) where -- Nat or Int here? nums : String → List Int -- catch - split returns empty strings that become zeros nums s = map stringToInt $ filter (_/=_ "") $ split (trim s) " " parse : String -> Maybe (List Round) parse s = mapM parseRound (split (trim s) "\n") pfunc pow : Int → Int → Int := `(x,y) => x ** y` part1 : List Round → Int part1 rounds = foldl _+_ 0 $ map score rounds where -- TODO we'll keep the math in Int land until we have magic Nat score : Round → Int score (a,b) = let count = natToInt $ length $ filter (\ n => elem n b) a in if count == 0 then 0 else pow 2 (count - 1) part2 : List Round → Int part2 rounds = go 0 $ map (_,_ 1) rounds where mark : Int -> Nat → List (Int × Round) → List (Int × Round) mark _ _ Nil = Nil mark v Z rounds = rounds mark v (S k) ((cnt, round) :: rounds) = (cnt + v, round) :: mark v k rounds go : Int → List (Int × Round) → Int go acc Nil = acc go acc ((cnt, a, b) :: rounds) = let n = length $ filter (\ n => elem n b) a in go (acc + cnt) $ mark cnt n rounds run : String -> IO Unit run fn = do putStrLn fn text <- readFile fn let (Just cards) = parse text | _ => putStrLn "fail" putStrLn "part1" printLn (part1 cards) putStrLn "part2" printLn (part2 cards) -- 13/30 -- 25004/14427616 main : IO Unit main = do run "aoc2023/day4/eg.txt" run "aoc2023/day4/input.txt"