module Day6 import Prelude import Node import Aoc Problem : U Problem = List (Int × Int) pNums : String → Either String (List Int) pNums line = let (_ :: line :: Nil) = split line ": " | _ => Left "expected two parts" in Right $ nums line parse : String → Either String Problem parse content = do let (a :: b :: Nil) = split (trim content) "\n" | _ => Left "expected two lines" times <- pNums a dists <- pNums b Right (zip times dists) part1 : Problem → Int part1 prob = go 1 prob where run : Int -> Int -> Int → Int → Int run time dist t count = let count = if dist < t * (time - t) then count + 1 else count in if time == t then count else run time dist (t + 1) count go : Int → Problem → Int go acc Nil = acc go acc ((time,dist) :: prob) = go (acc * run time dist 0 0) prob part2 : Int × Int → IO Unit part2 (time,dist) = do let t = intToDouble time let d = intToDouble dist let x = sqrtDouble (t * t - intToDouble 4 * d) let start = (t - x) / intToDouble 2 let stop = (t + x) / intToDouble 2 let s = doubleToInt $ ceilDouble start let e = doubleToInt $ ceilDouble stop putStrLn $ "part2 " ++ show (e - s) parse2 : String → Either String (Int × Int) parse2 content = let (a :: b :: Nil) = split (trim content) "\n" | _ => Left "too many parts" in let time = stringToInt $ pack $ filter isDigit $ unpack a dist = stringToInt $ pack $ filter isDigit $ unpack b in Right (time, dist) run : String -> IO Unit run fn = do putStrLn fn text <- readFile fn let (Right prob) = parse text | Left err => putStrLn err putStrLn $ debugStr prob putStrLn $ "part1 " ++ show (part1 prob) let (Right prob) = parse2 text | Left err => putStrLn err part2 prob -- debugLog prob -- part2 prob -- 288 / 71503 -- 1413720 / 30565288 main : IO Unit main = do run "aoc2023/day6/eg.txt" run "aoc2023/day6/input.txt"