Skip to content

Instantly share code, notes, and snippets.

@aaronjeline
Created December 5, 2021 17:05
Show Gist options
  • Save aaronjeline/7eca6bba8675e6508d81620b59a7540e to your computer and use it in GitHub Desktop.
Save aaronjeline/7eca6bba8675e6508d81620b59a7540e to your computer and use it in GitHub Desktop.
#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