aoc2023/day6.quox

113 lines
3.3 KiB
Text
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.

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)))