diff --git a/lib.rkt b/lib.rkt index 25db457..ac38f4f 100644 --- a/lib.rkt +++ b/lib.rkt @@ -9,6 +9,7 @@ (provide problem-input show-solution + uncurry sum neq? nzero? @@ -19,6 +20,7 @@ list-ref* chunks-of transpose + zip list->queue vector-ref* vector-set!*) @@ -38,6 +40,13 @@ (printf "Part 1: ~a\nPart 2: ~a\n" part1 part2)) +;; Function helpers ;; + +;; uncurry : (a1 -> ... -> an -> b) -> ((listof a) -> b) +(define uncurry + (curry apply)) + + ;; Number helpers ;; ;; sum : (listof number) -> number @@ -107,6 +116,10 @@ [layers (map cdr layers)]) (cons pixels (transpose layers))))) +;; zip : (a1 -> ... -> an -> b) -> (listof a1) -> ... -> (listof an) -> (listof b) +(define (zip f . lsts) + (map (curry apply f) (transpose lsts))) + ;; list->queue : (listof any) -> (queueof any) ;; Creates a queue and adds elements of list in order (define (list->queue lst) diff --git a/src/10.rkt b/src/10.rkt index 6cea41e..9d6a863 100644 --- a/src/10.rkt +++ b/src/10.rkt @@ -8,53 +8,66 @@ (define width (string-length (car input))) (define height (length input)) -(define (coprime? ij) - (= 1 (gcd (first ij) - (second ij)))) +(define (out-of-range? x y) + (or (< x 0) + (< y 0) + (>= x width) + (>= y height))) + +(define (coprime? i j) + (= 1 (gcd i j))) (define (offsets x y) - (define is - (range (negate x) (- width x))) - (define js - (range (negate y) (- height y))) - (filter coprime? (cartesian-product is js))) + (let ([is (range (negate x) (- width x))] + [js (range (negate y) (- height y))]) + (filter (uncurry coprime?) (cartesian-product is js)))) -(define (asteroid? xy) - (define row (list-ref input (second xy))) - (eq? #\# (string-ref row (first xy)))) +(define (asteroid? x y) + (define row (list-ref input y)) + (eq? #\# (string-ref row x))) -(define (asteroid-offset? x y ij) - (define i (first ij)) - (define j (second ij)) - (define max-multiple - (let ([max-x - (cond - [(zero? i) width] - [(positive? i) (truncate (/ (- (sub1 width) x) i))] - [else (abs (truncate (/ x i)))])] - [max-y - (cond - [(zero? j) height] - [(positive? j) (truncate (/ (- (sub1 height) y) j))] - [else (abs (truncate (/ y j)))])]) - (min max-x max-y))) - (ormap (λ (m) (asteroid? `(,(+ x (* m i)) - ,(+ y (* m j))))) - (range 1 (add1 max-multiple)))) +(define (asteroid-offset x y i j) + (let loop ([m 1]) + (let ([x* (+ x (* i m))] + [y* (+ y (* j m))]) + (cond + [(out-of-range? x* y*) #f] + [(asteroid? x* y*) (list x* y*)] + [else (loop (add1 m))])))) -(define (asteroids xy) - (define x (first xy)) - (define y (second xy)) - (count (curry asteroid-offset? x y) (offsets x y))) +(define (asteroids x y) + (filter-map (uncurry (curry asteroid-offset x y)) (offsets x y))) -(define-values (part1 location) +(define-values (part1 location in-view) (let* ([cols (range width)] [rows (range height)] - [locations (filter asteroid? (cartesian-product cols rows))] - [asteroid-counts (map asteroids locations)] - [maximum (apply max asteroid-counts)] - [index (index-of asteroid-counts maximum)] - [location (list-ref locations index)]) - (values maximum location))) + [locations (filter (uncurry asteroid?) (cartesian-product cols rows))] + [in-views (map (uncurry asteroids) locations)] + [counts (map length in-views)] + [maximum (apply max counts)] + [index (index-of counts maximum)]) + (values maximum + (list-ref locations index) + (list-ref in-views index)))) -(show-solution part1 #f) \ No newline at end of file +(define (offset