88 lines
2.8 KiB
Text
88 lines
2.8 KiB
Text
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)))
|