75 lines
2.0 KiB
Agda
75 lines
2.0 KiB
Agda
module Day6
|
||
|
||
import Prelude
|
||
import Node
|
||
import Aoc
|
||
|
||
data Oper = Plus | Times
|
||
|
||
getOp : Char → Maybe Oper
|
||
getOp '+' = Just Plus
|
||
getOp '*' = Just Times
|
||
getOp _ = Nothing
|
||
|
||
head' : ∀ a. List a → Maybe a
|
||
head' (x :: xs) = Just x
|
||
head' _ = Nothing
|
||
|
||
transpose : ∀ a. List (List a) → List (List a)
|
||
transpose {a} Nil = Nil
|
||
transpose {a} (Nil :: xs) = Nil
|
||
transpose {a} xs = mapMaybe head' xs :: transpose (map tail xs)
|
||
|
||
calc : List (List Int) → List Oper → Int
|
||
calc rows ops = foldl _+_ 0 $ map go $ zip ops $ rows
|
||
where
|
||
go : Oper × List Int → Int
|
||
go (Plus, nums) = foldl _+_ 0 nums
|
||
go (Times, nums) = foldl _*_ 1 nums
|
||
|
||
part1 : String → Int
|
||
part1 text =
|
||
let lines = split (trim text) "\n" in
|
||
case reverse lines of
|
||
Nil => -1
|
||
last :: rest =>
|
||
let key = unpack last
|
||
in calc (transpose (map (splitLine 0 key ∘ unpack) rest)) $ mapMaybe getOp key
|
||
where
|
||
splitLine : Int → List Char → List Char → List Int
|
||
splitLine acc (a :: b :: cs) (d :: ds) =
|
||
if b == ' '
|
||
then let acc = if d == ' ' then acc else acc * 10 + (ord d - 48)
|
||
in splitLine acc (b :: cs) ds
|
||
else acc :: splitLine 0 (b :: cs) ds
|
||
splitLine acc _ (d :: ds) =
|
||
let acc = if d == ' ' then acc else acc * 10 + (ord d - 48)
|
||
in splitLine acc Nil ds
|
||
splitLine acc _ Nil = acc :: Nil
|
||
|
||
part2 : String → Int
|
||
part2 text =
|
||
let lines = split (trim text) "\n" in
|
||
case reverse lines of
|
||
Nil => -1
|
||
last :: rest =>
|
||
let key = unpack last
|
||
in calc (splitOn 0 $ map (packNum 0) $ transpose $ map unpack $ reverse rest) $ mapMaybe getOp key
|
||
where
|
||
packNum : Int → List Char → Int
|
||
packNum acc Nil = acc
|
||
packNum acc (' ' :: cs) = packNum acc cs
|
||
packNum acc (c :: cs) = packNum (acc * 10 + (ord c - 48)) cs
|
||
|
||
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 "aoc2025/day6/eg.txt"
|
||
run "aoc2025/day6/input.txt"
|