aoc2023/day4.quox

102 lines
3.2 KiB
Plaintext
Raw Normal View History

2023-12-06 21:47:23 -05:00
-- 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'))
2023-12-09 09:15:31 -05:00
def all-members : ω.Line → List =
λ ln ⇒ list.filter (λ n ⇒ mem n (snd ln)) (fst ln)
2023-12-06 21:47:23 -05:00
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 → =
2023-12-09 09:15:31 -05:00
λ ln ⇒ score-from-len (all-members ln)
2023-12-06 21:47:23 -05:00
def total-score : ω.(List Line) → =
list.foldlω Line 0 (λ n l ⇒ nat.plus n (score l))
2023-12-09 09:15:31 -05:00
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)
2023-12-06 21:47:23 -05:00
#[main]
2023-12-09 09:15:31 -05:00
def part2 =
2023-12-06 21:47:23 -05:00
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
2023-12-09 09:15:31 -05:00
total-cards lines))