Day 3: Cleanup-ish.

This commit is contained in:
Jonathan Chan 2019-12-03 21:20:46 -08:00
parent 55d036e9a6
commit 12256fa329
1 changed files with 59 additions and 33 deletions

View File

@ -13,75 +13,101 @@
[wire2 (string->wire (second input))]) [wire2 (string->wire (second input))])
(values wire1 wire2))) (values wire1 wire2)))
;; step-path : boolean -> path -> (number . number) -> hashtable -> procedure -> (number . number) ;; To store the paths of each wire, we will use a hashtable.
;; The keys of the hashtable are positions on the grid,
;; stored as a pair of numbers (x . y).
;; The values of the hashtable are points on the grid,
;; which contain four pieces of information:
;; - first-visited? : Whether the first wire has traversed the point;
;; - first-steps : How many steps from the origin the first wire has taken;
;; - second-visited?, second-steps: idem but for the second wire.
(define pos-x car)
(define pos-y cdr)
(define (pos x y)
(cons x y))
(struct point
(first-visited?
first-steps
second-visited?
second-steps))
(define origin (pos 0 0))
(define default-point (point #f 0 #f 0))
;; step-path : boolean -> path -> hashtable -> (pos . number) -> (pos . number)
;; first-wire? : Indicates whether we're stepping for the first or second wire. ;; first-wire? : Indicates whether we're stepping for the first or second wire.
;; path : A pair (s: symbol . n: number), where s indicates the direction we step ;; path : A pair (s: symbol . n: number), where s indicates the direction we step
;; (R, L, U, D for right (+x), left (-x), up (+y), down (-y)) ;; (R, L, U, D for right (+x), left (-x), up (+y), down (-y))
;; and n indicates the number of units we step in that direction ;; and n indicates the number of units we step in that direction
;; position : A pair (x . y) that indicates the current location ;; pos-count : A pair (pos . number) that indicates the current location and the steps taken
;; hashtable : A map from positions to ((boolean . number) . (boolean . number))that indicate ;; hashtable : A map from pos to point
;; the total number of steps to get to that position and
;; whether the first or second wire has visited that position
;; Returns the new position after stepping ;; Returns the new position after stepping
(define (step-path first-wire? path pos-count ht) (define (step-path first-wire? path ht pos-count)
(let* ([position (car pos-count)] (let* ([position (car pos-count)]
[count (cdr pos-count)] [count (cdr pos-count)]
[x (car position)] [x (car position)]
[y (cdr position)] [y (cdr position)]
[update (λ (dir) [update (curry
(λ (i count) (λ (dir i count)
(let* ([key (match dir (let* ([key (match dir
['x (cons i y)] ['x (pos i y)]
['y (cons x i)])] ['y (pos x i)])]
[value (hash-ref ht key '((#f . 0) . (#f . 0)))] [value (hash-ref ht key default-point)]
[new-count (add1 count)] [new-count (add1 count)]
[new-value [new-value
(if first-wire? (if first-wire?
(cons `(#t . ,new-count) (cdr value)) (point #t new-count
(cons (car value) `(#t . ,new-count)))]) (point-second-visited? value)
(hash-set! ht key new-value) (point-second-steps value))
new-count)))]) (point (point-first-visited? value)
(point-first-steps value)
#t new-count))])
(hash-set! ht key new-value)
new-count)))])
(match path (match path
[`(R . ,(? number? n)) [`(R . ,(? number? n))
(cons (cons (+ x n) y) (cons (pos (+ x n) y)
(foldl (update 'x) count (range (add1 x) (add1 (+ x n)))))] (foldl (update 'x) count (range (add1 x) (add1 (+ x n)))))]
[`(L . ,(? number? n)) [`(L . ,(? number? n))
(cons (cons (- x n) y) (cons (pos (- x n) y)
(foldl (update 'x) count (reverse (range (- x n) x))))] (foldl (update 'x) count (reverse (range (- x n) x))))]
[`(U . ,(? number? n)) [`(U . ,(? number? n))
(cons (cons x (+ y n)) (cons (pos x (+ y n))
(foldl (update 'y) count (range (add1 y) (add1 (+ y n)))))] (foldl (update 'y) count (range (add1 y) (add1 (+ y n)))))]
[`(D . ,(? number? n)) [`(D . ,(? number? n))
(cons (cons x (- y n)) (cons (pos x (- y n))
(foldl (update 'y) count (reverse (range (- y n) y))))]))) (foldl (update 'y) count (reverse (range (- y n) y))))])))
(define (step-wire first-wire? wire ht) (define (step-wire first-wire? wire ht)
(foldl (λ (path pos-count) (step-path first-wire? path pos-count ht)) '((0 . 0) . 0) wire)) (foldl (λ (path pos-count) (step-path first-wire? path ht pos-count)) `(,origin . 0) wire))
(define-values (part1 intersections) (define-values (part1 intersect-points)
(let* ([hashtable (make-hash '(((0 . 0) . ((#f . 0) . (#f . 0)))))] (let* ([hashtable (make-hash)]
[_ (step-wire #t wire1 hashtable)] [_ (step-wire #t wire1 hashtable)]
[_ (step-wire #f wire2 hashtable)] [_ (step-wire #f wire2 hashtable)]
[hashlist (hash->list hashtable)] [hashlist (hash->list hashtable)]
[intersections [intersections
(filter (λ (kv) (filter (λ (kv)
(let ([v (cdr kv)]) (let ([v (cdr kv)])
(and (caar v) (cadr v)))) (and (point-first-visited? v)
(point-second-visited? v))))
hashlist)] hashlist)]
[distances [distances
(map (λ (kv) (map (λ (kv)
(let ([k (car kv)]) (let ([k (car kv)])
(+ (abs (car k)) (abs (cdr k))))) (+ (abs (pos-x k))
(abs (pos-y k)))))
intersections)]) intersections)])
(values (apply min distances) (values (apply min distances)
intersections))) (map cdr intersections))))
(define part2 (define part2
(let* ([steps (let* ([steps
(map (λ (kv) (map (λ (v)
(let ([v (cdr kv)]) (+ (point-first-steps v)
(+ (cdar v) (cddr v)))) (point-second-steps v)))
intersections)]) intersect-points)])
(apply min steps))) (apply min steps)))
(show-solution part1 part2) (show-solution part1 part2)