module Day1 import Prelude import Node import Aoc pairUp : List Int -> List (Int × Int) pairUp (a :: b :: rest) = (a,b) :: pairUp rest pairUp (a :: rest) = trace "fail" Nil pairUp Nil = Nil dist : (Int × Int) → Int dist (a,b) = if a < b then b - a else a - b part1 : String -> Int part1 text = let pairs = pairUp $ join $ map nums $ split text "\n" left = qsort _<_ $ map fst pairs right = qsort _<_ $ map snd pairs dists = map dist $ zip left right in foldl _+_ 0 dists lookup : ∀ a b. {{Eq a}} → a → List (a × b) → Maybe b lookup key Nil = Nothing lookup key ((k,v) :: rest) = if k == key then Just v else lookup key rest coalesce : List Int → Int -> List (Int × Int) coalesce (a :: b :: rest) cnt = if a == b then coalesce (b :: rest) (cnt + 1) else (a,cnt) :: coalesce (b :: rest) 1 coalesce (a :: Nil) cnt = (a,cnt) :: Nil coalesce Nil cnt = Nil cross : List (Int × Int) → List (Int × Int) → Int → Int cross xs ys acc = let ((a,cnt) :: xs') = xs | Nil => acc in let ((b,cnt') :: ys') = ys | Nil => acc in if a == b then cross xs' ys' (acc + a * cnt * cnt') else if a < b then cross xs' ys acc else cross xs ys' acc part2 : String → Int part2 text = let pairs = pairUp $ join $ map nums $ split text "\n" left = coalesce (qsort _<_ $ map fst pairs) 1 right = coalesce (qsort _<_ $ map snd pairs) 1 in cross left right 0 run : String -> IO Unit run fn = do putStrLn fn text <- readFile fn putStrLn $ "part1 " ++ show (part1 text) putStrLn $ "part2 " ++ show (part2 text) main : IO Unit main = do run "aoc2024/day1/eg.txt" run "aoc2024/day1/input.txt"