aoc2023/day6.quox

114 lines
3.3 KiB
Plaintext
Raw Normal View History

2023-12-06 21:47:23 -05:00
load "string.quox"
load "io.quox"
namespace real {
postulate0 : ★
#[compile-scheme "inexact"]
postulate to- :
#[compile-scheme "sqrt"]
postulate sqrt :
#[compile-scheme "(lambda (x) (exact (floor x)))"]
postulate floor :
#[compile-scheme "(lambda (x) (exact (ceiling x)))"]
postulate ceiling :
#[compile-scheme "(lambda% (x y) (+ x y))"]
postulate plus :
#[compile-scheme "(lambda% (x y) (- x y))"]
postulate minus :
#[compile-scheme "(lambda% (x y) (* x y))"]
postulate times :
#[compile-scheme "(lambda% (x y) (/ x y))"]
postulate divide :
#[compile-scheme "(lambda% (x y) (if (< x y) 'true 'false))"]
postulate lt : ω. → ω. → Bool
def negate : = λ x ⇒ minus (to- 0) x
def quad : ω. → ω. → ω. × =
λ a b c ⇒
letω res =
(λ op ⇒
let disc = minus (times b b) (times (to- 4) (times a c)) in
divide (op (negate b) (sqrt disc)) (times (to- 2) a))
∷ () → in
letω ordered =
(λ x y ⇒ bool.if ( × ) (lt x y) (x, y) (y, x)) ∷ ω. → ω. × in
ordered (res plus) (res minus)
}
def0 = real.
def to- = real.to-
def range : ω. → ω. × =
λ t d ⇒
letω d = to- d; t = to- t;
res = real.quad (real.negate (to- 1)) t (real.negate d);
lo = fst res; hi = snd res
in (real.ceiling lo, real.floor hi)
def result : ω.( × ) → =
λ td ⇒ letω r = range (fst td) (snd td) in succ (nat.minus (snd r) (fst r))
def0 Game : ★ = ×
def to-' : String → =
λ s ⇒ maybe.fold 0 (λ n ⇒ n) (string.to- s)
def split-line : ω.String → List =
λ l ⇒
letω strings = string.split char.ws? l;
strings = list.filter String string.not-null strings;
strings = list.tail-or-nil String strings in
list.map String to-' strings
def split-file : ω.String → List Game =
λ str ⇒
letω both = string.break (λ c ⇒ char.eq c char.newline) str;
one = fst both; two = snd both;
times = split-line one; distances = split-line two in
list.zip-with-uneven Game (λ t d ⇒ (t, d)) times distances
def space? : ω.Char → Bool = λ c ⇒ char.eq c char.space
def squash : ω.String → String =
λ s ⇒
letω nonws? = (λ c ⇒ bool.not (char.ws? c)) ∷ ω.Char → Bool in
string.from-list (list.filter Char nonws? (string.to-list s))
def from-line : ω.String → =
λ s ⇒ letω s = snd (string.break space? s) in to-' (squash s)
def nonsplit-file : ω.String → Game =
λ str ⇒
letω both = string.break (λ c ⇒ char.eq c char.newline) str;
one = fst both; two = snd both in
(from-line one, from-line two)
def product : List = list.foldl 1 nat.times
def part1 =
io.bindω String True
(io.read-fileω "in/day6")
(λ s ⇒ io.dump (product (list.mapω Game result (split-file s))))
#[main]
def part2 =
io.bindω String True
(io.read-fileω "in/day6")
(λ s ⇒ io.dump (result (nonsplit-file s)))