diff --git a/3.rkt b/3.rkt index df4e91a..52d591e 100644 --- a/3.rkt +++ b/3.rkt @@ -4,67 +4,49 @@ ;; solution for day 3 +(define *delta* '((0 . 1) (1 . 1) (1 . 0) + (1 . -1) (0 . -1) (-1 . -1) + (-1 . 0) (-1 . 1))) + +(define (posn+ a b) + (cons (+ (car a) (car b)) + (+ (cdr a) (cdr b)))) + (define (part1 input) - (define (input-ref grid y x) - (string-ref (vector-ref grid y) x)) - - (define (symbol-adjacent? grid y x) - (for/or ([delta (in-list '((0 . 1) (1 . 1) (1 . 0) - (1 . -1) (0 . -1) (-1 . -1) - (-1 . 0) (-1 . 1)))] - #:unless (>= (+ (car delta) x) (string-length (vector-ref grid y))) - #:unless (< (+ (car delta) x) 0) - #:unless (>= (+ (cdr delta) y) (vector-length grid)) - #:unless (< (+ (cdr delta) y) 0)) - (match (input-ref grid (+ (cdr delta) y) (+ (car delta) x)) - [(or #\. #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) #f] - [_ #t]))) - - (for/sum ([line (in-vector input)] [y (in-naturals)]) - (for/sum ([posn (in-list (regexp-match-positions* #px"[0-9]+" line))] - #:do [(define xmin (car posn)) (define xmax (cdr posn))]) - (if (for/or ([x (in-range xmin xmax)]) (symbol-adjacent? input y x)) - (string->number (substring line xmin xmax)) - 0)))) - + (define numbers + (for/set ([(pos elem) (in-hash input)] + #:when (char? elem) + [d (in-list *delta*)] + #:do [(define neigh (hash-ref input (posn+ pos d) #f))] + #:when (list? neigh)) + neigh)) + (for/sum ([n (in-set numbers)]) + (third n))) (define (part2 input) - (define (input-ref grid y x) - (string-ref (vector-ref grid y) x)) - - (define (find-adj-numbers grid y x) - (for/list ([delta (in-list '((0 . 1) (1 . 1) (1 . 0) - (1 . -1) (0 . -1) (-1 . -1) - (-1 . 0) (-1 . 1)))] - #:unless (>= (+ (car delta) x) (string-length (vector-ref grid y))) - #:unless (< (+ (car delta) x) 0) - #:unless (>= (+ (cdr delta) y) (vector-length grid)) - #:unless (< (+ (cdr delta) y) 0) - #:when (member (input-ref grid (+ (cdr delta) y) (+ (car delta) x)) - '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))) - (cons (+ (car delta) x) (+ (cdr delta) y)))) - - (define nums (make-hash)) - - (for ([line (in-vector input)] [y (in-naturals)]) - (for ([posn (in-list (regexp-match-positions* #px"[0-9]+" line))] - #:do [(define xmin (car posn)) (define xmax (cdr posn))]) - (for ([x (in-range xmin xmax)]) - (hash-set! nums (cons x y) (list xmin y (string->number (substring line xmin xmax))))))) - - (for/sum ([line (in-vector input)] [y (in-naturals)]) - (for/sum ([chr (in-list (string->list line))] [x (in-naturals)] - #:when (equal? chr #\*)) - (define adj-nums (find-adj-numbers input y x)) - (define adj-num-entries - (for/set ([a-n (in-list adj-nums)]) - (hash-ref nums a-n))) - (if (= 2 (set-count adj-num-entries)) - (apply * (map #{third %} (set->list adj-num-entries))) - 0)))) + (for/sum ([(pos elem) (in-hash input)] + #:when (equal? elem #\*) + #:do [(define neighs + (for/set ([d (in-list *delta*)] + #:do [(define neigh (hash-ref input (posn+ pos d) #f))] + #:when (list? neigh)) + neigh))] + #:when (= 2 (set-count neighs))) + (apply * (map third (set->list neighs))))) (define (parse fname) - (list->vector (file->lines fname))) + (define elements (make-hash)) + (for ([line (in-lines (open-input-file fname))] [y (in-naturals)] + #:do [(for ([posn (in-list (regexp-match-positions* #px"[0-9]+" line))] + #:do [(match-define (cons xmin xmax) posn)] + [x (in-range xmin xmax)]) + (hash-set! elements (cons y x) + (list y xmin (string->number (substring line xmin xmax)))))] + [chr (in-string line)] [x (in-naturals)] + #:unless (equal? chr #\.) + #:unless (char-numeric? chr)) + (hash-set! elements (cons y x) chr)) + elements) (module+ main (define input (parse "inputs/3"))