module Day1

import Prelude
import Node

digits1 : List Char -> List Int
digits1 Nil = Nil
digits1 (c :: cs) = let x = ord c in
  if 48 < x && x < 58
    then x - 48 :: digits1 cs
    else digits1 cs

-- TODO I used @ patterns in Lean
digits2 : List Char -> List Int
digits2 xs = case xs of
    ('o' :: 'n' :: 'e' :: _) => 1 :: digits2 (tail xs)
    ('t' :: 'w' :: 'o' :: _) => 2 :: digits2 (tail xs)
    ('t' :: 'h' :: 'r' :: 'e' :: 'e' :: _) => 3 :: digits2 (tail xs)
    ('f' :: 'o' :: 'u' :: 'r' :: _) => 4 :: digits2 (tail xs)
    ('f' :: 'i' :: 'v' :: 'e' :: _) => 5 :: digits2 (tail xs)
    ('s' :: 'i' :: 'x' :: _) => 6 :: digits2 (tail xs)
    ('s' :: 'e' :: 'v' :: 'e' :: 'n' :: _) => 7 :: digits2 (tail xs)
    ('e' :: 'i' :: 'g' :: 'h' :: 't' :: _) => 8 :: digits2 (tail xs)
    ('n' :: 'i' :: 'n' :: 'e' :: _) => 9 :: digits2 (tail xs)
    (c :: cs) => let x = ord c in
        case x < 58 of
          True => case 48 < x of
            True => x - 48 :: digits2 cs
            False => digits2 cs
          False => digits2 cs
    Nil => Nil


combine : List Int -> Int
combine Nil = 0
combine (x :: Nil) = x * 10 + x
combine (x :: y :: Nil) = x * 10 + y
combine (x :: y :: xs) = combine (x :: xs)

part1 : String -> (String -> List Int) -> Int
part1 text digits =
  let lines = split (trim text) "\n" in
  let nums = map combine $ map digits lines in
  foldl _+_ 0 nums

#check digits1 ∘ unpack : String -> List Int

runFile : String -> IO Unit
runFile fn = do
  text <- readFile fn
  putStrLn fn
  putStrLn "part1"
  putStrLn $ show (part1 text (digits1 ∘ unpack))
  putStrLn "part2"
  putStrLn $ show (part1 text (digits2 ∘ unpack))
  putStrLn ""


-- Argument is a hack to keep it from running at startup.  Need to add IO
main : IO Unit
main = do
  runFile "aoc2023/day1/eg.txt"
  runFile "aoc2023/day1/eg2.txt"
  runFile "aoc2023/day1/input.txt"
