aoc2023/day4.quox

102 lines
3.2 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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 : ω.Line → List =
λ ln ⇒ list.filter (λ n ⇒ mem n (snd ln)) (fst ln)
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 ln)
def total-score : ω.(List Line) → =
list.foldlω Line 0 (λ n l ⇒ nat.plus n (score l))
def part1 =
io.bindω String True
(io.read-fileω "in/day4")
(λ s ⇒ io.dump (List Line)
(letω lines = string.split (char.eq char.newline) s;
lines = list.mapω String Line split-line lines in
lines))
def0 Copies : ★ = List
def CNil = list.Nil
def CCons = list.Cons
def decr-copies : Copies → × Copies =
let0 Ret : ★ = × Copies in
list.foldr Ret (1, CNil)
(λ cur nrest ⇒
case nrest return Ret of { (n, rest) ⇒
case cur return Ret of {
0 ⇒ (n, rest);
succ cur ⇒ (succ n, CCons cur rest)
}})
def new-copies : → ω. → Copies → Copies =
λ count value cs ⇒
case count return Copies of {
0 ⇒ cs;
succ _, cs' ⇒ CCons value cs'
}
def total-cards : ω.(List Line) → =
λ lines ⇒
let 0.State : ★ = × Copies;
ω.start : State = (0, CNil);
ω.next : ω.State → ω.Line → State =
λ st ln ⇒
letω total = fst st;
nc = decr-copies (snd st);
copies-this = fst nc;
copies-rest = snd nc;
score1 = list.length (all-members ln);
copies-out = new-copies copies-this score1 copies-rest;
total' = nat.plus total copies-this in
(total', copies-out) in
fst (list.foldlω Line State start next lines)
#[main]
def part2 =
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-cards lines))