Created
December 5, 2021 17:05
-
-
Save aaronjeline/7eca6bba8675e6508d81620b59a7540e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang racket | |
(require threading) | |
(module+ test (require rackunit)) | |
(struct line (from to) #:transparent) | |
(struct posn (x y) #:transparent) | |
(define (parse-line l) | |
(match (string-split l "->") | |
[(list to from) | |
(line (parse-cord to) (parse-cord from))])) | |
(define (parse-cord c) | |
(match (string-split c ",") | |
[(list x y) | |
(posn (string->number (string-trim x)) | |
(string->number (string-trim y)))])) | |
(module+ test | |
(check-equal? (parse-line "0,9 -> 5,9") | |
(line (posn 0 9) (posn 5 9)))) | |
(define (line-x1 line) | |
(posn-x (line-from line))) | |
(define (line-x2 line) | |
(posn-x (line-to line))) | |
(define (line-y1 line) | |
(posn-y (line-from line))) | |
(define (line-y2 line) | |
(posn-y (line-to line))) | |
(define (horizontal-or-vertical? line) | |
(or | |
(= (line-x1 line) (line-x2 line)) | |
(= (line-y1 line) (line-y2 line)))) | |
(module+ test | |
(check-true (horizontal-or-vertical? | |
(line (posn | |
1 1) | |
(posn | |
1 3))))) | |
(define (compute-range v1 v2) | |
(stream->list | |
(in-range | |
(min v1 v2) | |
(max (add1 v1) (add1 v2))))) | |
(define/contract (h-or-v-line->points line) | |
(-> horizontal-or-vertical? list?) | |
(define h-range | |
(compute-range (line-x1 line) (line-x2 line))) | |
(define v-range | |
(compute-range (line-y1 line) (line-y2 line))) | |
(map (λ (p) (apply posn p)) | |
(cartesian-product h-range v-range))) | |
(define (posn-min p1 p2) | |
(if (and | |
(<= (posn-x p1) (posn-x p2)) | |
(<= (posn-y p1) (posn-y p2))) | |
p1 p2)) | |
(define (posn-max p1 p2) | |
(if (and | |
(> (posn-x p1) (posn-x p2)) | |
(> (posn-y p1) (posn-y p2))) | |
p1 p2)) | |
(define (posn+ p1 p2) | |
(posn (+ (posn-x p1) (posn-x p2)) | |
(+ (posn-y p1) (posn-y p2)))) | |
(define (line-trace from to Δ) | |
(if (equal? from to) | |
(list from) | |
(cons from (line-trace (posn+ from Δ) to Δ)))) | |
(module+ test | |
(check-equal? | |
(line-trace (posn 1 1) (posn 3 3) (posn 1 1)) | |
(list->list-posns '((1 1) (2 2) (3 3)))) | |
(check-equal? | |
(line-trace (posn 9 7) (posn 7 9) (posn -1 1)) | |
(list->list-posns '((9 7) (8 8) (7 9))))) | |
(define (compute-Δ p1 p2) | |
(posn | |
(if (< (posn-x p1) (posn-x p2)) | |
1 | |
-1) | |
(if (< (posn-y p1) (posn-y p2)) | |
1 | |
-1))) | |
(module+ test | |
(check-equal? | |
(compute-Δ (posn 1 1) (posn 3 3)) | |
(posn 1 1)) | |
(check-equal? | |
(compute-Δ (posn 9 7) (posn 7 9)) | |
(posn -1 1))) | |
(define (diag-line->points line) | |
(line-trace | |
(line-from line) (line-to line) | |
(compute-Δ (line-from line) (line-to line)))) | |
(module+ test | |
(check-equal? | |
(list->set | |
(diag-line->points (line (posn 1 1) (posn 3 3)))) | |
(list->set | |
(list->list-posns '((1 1) (2 2) (3 3))))) | |
(check-equal? | |
(list->set | |
(diag-line->points (line (posn 9 7) (posn 7 9)))) | |
(list->set | |
(list->list-posns '((9 7) (8 8) (7 9)))))) | |
(define (list->list-posns l) | |
(map (λ (p) (apply posn p)) l)) | |
(define (line->points line) | |
(if (horizontal-or-vertical? line) | |
(h-or-v-line->points line) | |
(diag-line->points line))) | |
(module+ test | |
(check-equal? | |
(h-or-v-line->points (line (posn 1 1) (posn 1 3))) | |
(list->list-posns `((1 1) (1 2) (1 3)))) | |
(check-equal? | |
(list->set (h-or-v-line->points (line (posn 9 7) (posn 7 7)))) | |
(list->set (list->list-posns `((9 7) (8 7) (7 7)))))) | |
(define locations (make-hash '())) | |
(define (inc! p) | |
(define cur (hash-ref! locations p 0)) | |
(hash-set! locations p (add1 cur))) | |
(define lines | |
(~>> | |
(with-input-from-file "/tmp/input" | |
(λ () | |
(port->lines (current-input-port)))) | |
(map parse-line))) | |
(for [(line (in-list lines))] | |
(for [(p (in-list (line->points line)))] | |
(inc! p))) | |
(define count 0) | |
(define (inc-count!) | |
(set! count (add1 count))) | |
(for [([p v] (in-hash locations))] | |
(when (> v 1) | |
(inc-count!))) | |
count | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment