79 lines
2.6 KiB
Text
79 lines
2.6 KiB
Text
|
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)))
|