module Day2

import Prelude
import Node
import Aoc

decr : List Int → Bool
decr (x :: y :: _) = y < x
decr _ = False

diff : Int → Int → Int
diff x y = if x < y then y - x else x - y

isSafe : Bool → List Int → Bool
isSafe decr (x :: y :: rest) =
  let d = diff x y
      good = 0 < d && d < 4
      safe = if x < y then not decr && good else decr && good in
  if safe then isSafe decr (y :: rest) else False
isSafe _ _ = True

check : List Int → Bool
check x = isSafe (decr x) x

any : ∀ a. (a → Bool) → List a → Bool
any f xs = foldl (_||_) False $ map f xs

alts : List Int → List (List Int)
alts Nil = Nil
alts (x :: xs) = xs :: map (_::_ x) (alts xs)

-- I want lean's #eval here

parse : String → List (List Int)
parse text = map nums $ split (trim text) "\n"

run : String -> IO Unit
run fn = do
  putStrLn fn
  text <- readFile fn
  let stuff = parse text
  let good = filter check stuff
  putStrLn $ "part1 " ++ show (length good)
  let good = filter (any check ∘ alts) stuff
  putStrLn $ "part2 " ++ show (length good)

main : IO Unit
main = do
  run "aoc2024/day2/eg.txt"
  run "aoc2024/day2/input.txt"

