load "bool.quox" load "list.quox" load "maybe.quox" load "int.quox" def0 Int = scheme-int.Int def zz = scheme-int.from-ℕ 0 def step : ω.(List Int) → List Int = λ xs ⇒ list.zip-with-uneven Int Int Int (λ m n ⇒ scheme-int.minus n m) xs (list.tail-or-nil Int xs) def all-zero : ω.(List Int) → Bool = list.foldlω Int Bool 'true (λ b n ⇒ bool.and b (scheme-int.eq n zz)) def last : 0.(A : ★) → ω.(List A) → Maybe A = λ A ⇒ list.foldrω A (Maybe A) (Nothing A) (λ x y ⇒ maybe.or A y (Just A x)) def0 last-ok : last ℕ (4, 1, 4, 8, 5, 'nil) ≡ Just ℕ 5 : Maybe ℕ = δ 𝑖 ⇒ Just ℕ 5 def last-or-0 : ω.(List Int) → Int = λ xs ⇒ maybe.fold Int Int zz (λ x ⇒ x) (last Int xs) def next-entry : ω.(List ℕ) → Int = λ xs ⇒ letω fuel = fst xs in letω xs = list.map ℕ Int scheme-int.from-ℕ xs in let result : Int = caseω fuel return ω.(List Int) → Int of { 0 ⇒ λ _ ⇒ zz; succ _, ω.rec ⇒ λ this ⇒ bool.if Int (all-zero this) zz (letω next : List Int = step this in letω diff : Int = rec next in scheme-int.plus diff (last-or-0 this)) } xs in result def sumZ = list.foldr Int Int zz scheme-int.plus {- def0 ok-1 : next-entry (6, 0, 3, 6, 9, 12, 15, 'nil) ≡ 18 : ℕ = δ _ ⇒ 18 def0 ok-2 : next-entry (6, 1, 3, 6, 10, 15, 21, 'nil) ≡ 28 : ℕ = δ _ ⇒ 28 def0 ok-3 : next-entry (6, 10, 13, 16, 21, 30, 45, 'nil) ≡ 68 : ℕ = δ _ ⇒ 68 -} load "io.quox" load "string.quox" def read-file : ω.String → IO [ω.List (List ℕ)] = λ path ⇒ letω split-lines : ω.String → List String = string.split (λ c ⇒ char.eq c char.newline); split-numbers : ω.String → List ℕ = λ str ⇒ let words = string.split char.ws? str in list.map String ℕ string.to-ℕ-or-0 words; split-file : ω.String → [ω. List (List ℕ)] = λ str ⇒ [list.mapω String (List ℕ) split-numbers (split-lines str)] in io.mapω String [ω.List (List ℕ)] split-file (io.read-fileω path) def FILE : String = "in/day9" #[main] def part1 = io.bindω (List (List ℕ)) True (read-file FILE) (λ lists ⇒ io.dump Int (sumZ (list.mapω (List ℕ) Int next-entry lists))) def part2 : IO True = letω next-entry-r : ω.(List ℕ) → Int = λ xs ⇒ next-entry (list.reverse ℕ xs) in io.bindω (List (List ℕ)) True (read-file FILE) (λ lists ⇒ io.dump Int (sumZ (list.mapω (List ℕ) Int next-entry-r lists)))