54 lines
1.8 KiB
Text
54 lines
1.8 KiB
Text
-- 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))
|