70 lines
1.7 KiB
Agda
70 lines
1.7 KiB
Agda
module Day2
|
||
|
||
import Prelude
|
||
import Node
|
||
import Aoc
|
||
|
||
parse : String → List (Int × Int)
|
||
parse text = map mkPair $ split text ","
|
||
where
|
||
mkPair : String → Int × Int
|
||
mkPair t = case split t "-" of
|
||
(a :: b :: Nil) => (stringToInt a, stringToInt b)
|
||
bad => fatalError "BAD \{t}"
|
||
|
||
invalid : String → Bool
|
||
invalid s =
|
||
let l = slen s
|
||
h = l / 2
|
||
in if h * 2 /= l then False
|
||
else go 0 h
|
||
where
|
||
go : Int → Int → Bool
|
||
go i h = if i == h
|
||
then True
|
||
else if sindex s i == sindex s (i + h) then go (i + 1) h else False
|
||
|
||
match : List Char → List Char → Bool
|
||
match pat cs = go pat cs
|
||
where
|
||
go : List Char → List Char → Bool
|
||
go (p :: ps) (c :: cs) = if p == c then go ps cs else False
|
||
go Nil Nil = True
|
||
go Nil cs = go pat cs
|
||
go (p :: ps) Nil = False
|
||
|
||
invalid' : String → Bool
|
||
invalid' s =
|
||
let l = slen s
|
||
h = l / 2
|
||
in check (S Z) (cast h) $ unpack s
|
||
where
|
||
check : Nat → Nat → List Char → Bool
|
||
check a h cs =
|
||
if a > h then False else
|
||
if match (take a cs) cs then True else check (S a) h cs
|
||
|
||
scan : (String → Bool) → Int → Int → Int → Int
|
||
scan invalid a b acc =
|
||
let acc = if invalid (show a) then acc + a else acc in
|
||
if a == b then acc else scan invalid (a + 1) b acc
|
||
|
||
part1 : String → Int
|
||
part1 text = foldl (\acc x => scan invalid (fst x) (snd x) acc) 0 $ parse text
|
||
|
||
part2 : String → Int
|
||
part2 text = foldl (\acc x => scan invalid' (fst x) (snd x) acc) 0 $ parse text
|
||
|
||
run : String -> IO Unit
|
||
run fn = do
|
||
putStrLn fn
|
||
text <- readFile fn
|
||
printLn $ parse text
|
||
putStrLn $ "part1 " ++ show (part1 text)
|
||
putStrLn $ "part2 " ++ show (part2 text)
|
||
|
||
main : IO Unit
|
||
main = do
|
||
run "aoc2025/day2/eg.txt"
|
||
run "aoc2025/day2/input.txt"
|