load "bool.quox" load "list.quox" load "maybe.quox" load "int.quox" def zz = int.zeroℤ def step : ω.(List ℤ) → List ℤ = λ xs ⇒ list.zip-with-uneven ℤ ℤ ℤ (λ m n ⇒ int.minus n m) xs (list.tail-or-nil ℤ xs) def all-zero : ω.(List ℤ) → Bool = list.foldlω ℤ Bool 'true (λ b n ⇒ bool.and b (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 ℤ) → ℤ = λ xs ⇒ maybe.fold ℤ ℤ zz (λ x ⇒ x) (last ℤ xs) {- def next-entries : ω.(List ℕ) → List ℕ = λ xs ⇒ letω fuel = fst xs in caseω fuel return ω.(List ℕ) → List ℕ of { 0 ⇒ λ _ ⇒ list.Nil ℕ; succ _, ω.rec ⇒ λ this ⇒ bool.if (List ℕ) (all-zero this) (list.Nil ℕ) (letω next : List ℕ = step this in letω rest : List ℕ = rec next in letω new : ℕ = nat.plus (last-or-0 this) (head-or-0 rest) in list.Cons ℕ new rest) } xs -} def next-entry : ω.(List ℕ) → ℕ = λ xs ⇒ letω fuel = fst xs in letω xs = list.map ℕ ℤ int.from-ℕ xs in let result : ℤ = caseω fuel return ω.(List ℤ) → ℤ of { 0 ⇒ λ _ ⇒ zz; succ _, ω.rec ⇒ λ this ⇒ bool.if ℤ (all-zero this) zz (letω next : List ℤ = step this in letω diff : ℤ = rec next in int.plus diff (last-or-0 this)) } xs in int.abs result 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 doot = io.bindω (List (List ℕ)) True (read-file FILE) (λ lists ⇒ io.dump (List (List ℕ)) lists) #[main] def part1 = io.bindω (List (List ℕ)) True (read-file FILE) (λ lists ⇒ io.dump ℕ (list.sum (list.mapω (List ℕ) ℕ next-entry lists)))