-- introducing: let expressions!!! -- i implemented them yesterday because this was just too annoying otherwise load "list.quox" load "string.quox" load "io.quox" def0 Line : ★ = List ℕ × List ℕ -- i still don't have char literals. quox has no idea what "a char" is def colon = char.from-ℕ 0x3A def bar = char.from-ℕ 0x7C def split-line : ω.String → Line = λ line ⇒ letω line = snd (string.break (char.eq colon) line); pair = string.break (char.eq bar) line; got = fst pair; want = snd pair; got = list.filter String string.not-null (string.split char.ws? got); want = list.filter String string.not-null (string.split char.ws? want); got = list.tail-or-nil String got; want = list.tail-or-nil String want; to-ℕs = list.map String ℕ (λ s ⇒ maybe.fold ℕ ℕ 0 (λ n ⇒ n) (string.to-ℕ s)) in (to-ℕs got, to-ℕs want) def mem : ω.ℕ → ω.(List ℕ) → Bool = λ n ⇒ list.foldlω ℕ Bool 'false (λ b n' ⇒ bool.or b (nat.eq n n')) def all-members : ω.(List ℕ) → ω.(List ℕ) → List ℕ = λ g w ⇒ list.filter ℕ (λ n ⇒ mem n w) g def score-from-len : ω.(List ℕ) → ℕ = λ xs ⇒ maybe.foldω (ℕ × List ℕ) ℕ 0 (λ xxs ⇒ list.foldlω ℕ ℕ 1 (λ c _ ⇒ nat.times 2 c) (snd xxs)) (list.uncons ℕ xs) def score : ω.Line → ℕ = λ ln ⇒ score-from-len (all-members (fst ln) (snd ln)) def total-score : ω.(List Line) → ℕ = list.foldlω Line ℕ 0 (λ n l ⇒ nat.plus n (score l)) #[main] def main = io.bindω String True (io.read-fileω "in/day4") (λ s ⇒ io.dump ℕ (letω lines = string.split (char.eq char.newline) s; lines = list.mapω String Line split-line lines in total-score lines))