You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
2.1 KiB
68 lines
2.1 KiB
#lang racket |
|
(require "lib/common.rkt" |
|
fancy-app) |
|
|
|
(struct segment (p1 p2) #:transparent) |
|
(struct posn (x y) #:transparent) |
|
|
|
(define (parse lines) |
|
(for/vector ([line (in-list lines)]) |
|
(match line |
|
[(pregexp #px"([0-9]*),([0-9]*) -> ([0-9]*),([0-9]*)" |
|
(list _ |
|
(app string->number x1) (app string->number y1) |
|
(app string->number x2) (app string->number y2))) |
|
(segment (posn x1 y1) (posn x2 y2))]))) |
|
|
|
(define (is-cardinal? seg) |
|
(match seg |
|
[(segment (posn x _) (posn x _)) #t] |
|
[(segment (posn _ y) (posn _ y)) #t] |
|
[_ #f])) |
|
|
|
(define (segment->point-set seg) |
|
(match seg |
|
[(segment (posn x y1) (posn x y2)) |
|
(define y-init (min y1 y2)) |
|
(for/vector ([i (in-inclusive-range 0 (abs (- y1 y2)))]) |
|
(posn x (+ i y-init)))] |
|
[(segment (posn x1 y) (posn x2 y)) |
|
(define x-init (min x1 x2)) |
|
(for/vector ([i (in-inclusive-range 0 (abs (- x1 x2)))]) |
|
(posn (+ i x-init) y))] |
|
[(segment (posn x1 y1) (posn x2 y2)) |
|
(define (direction a b) |
|
(if (<= a b) 1 -1)) |
|
(define x-direction (direction x1 x2)) |
|
(define y-direction (direction y1 y2)) |
|
(for/vector ([x (in-range x1 (+ x2 x-direction) x-direction)] |
|
[y (in-range y1 (+ y2 y-direction) y-direction)]) |
|
(posn x y))])) |
|
|
|
(define (day5a segments) |
|
(day5b (vector-filter is-cardinal? segments))) |
|
|
|
(define (day5b segments) |
|
(define covered (vector-map segment->point-set segments)) |
|
(define counts (make-hash)) |
|
(for* ([point-set (in-vector covered)] |
|
[point (in-vector point-set)]) |
|
(hash-update! counts point add1 0)) |
|
|
|
(length (filter (<= 2 _) (hash-values counts)))) |
|
|
|
(module+ main |
|
(call-with-input-file "data/day5.txt" |
|
(λ (prt) |
|
(define lines (parse (port->lines prt))) |
|
(answer 5 1 (day5a lines)) |
|
(answer 5 2 (day5b lines))))) |
|
|
|
(module+ test |
|
(require rackunit) |
|
|
|
(call-with-input-file "data/day5.test.txt" |
|
(λ (prt) |
|
(define lines (parse (port->lines prt))) |
|
(check-equal? (day5a lines) 5) |
|
(check-equal? (day5b lines) 12))))
|
|
|