#lang br
(require racket/file sugar rackunit racket/set)
(define lines (map (λ (s) (map (λ (s2) (define ints (map string->number (string-split s2 ",")))
(+ (first ints) (* +i (second ints)))) (string-split s " -> "))) (file->lines "05.rktd")))
(define (Line-not-diagonal line)
(match line
[(list left right) (or (= (real-part left) (real-part right)) (= (imag-part left) (imag-part right)))]))
;; why does make-polar cause the solution to run faster?
;; both functions create an imaginary number
;; make-polar is slower to create the numbers (because it has to call trig functions)
;; but storing the polar numbers with frequency-hash is much faster
;; using inexact coefficients makes make-rectangular go faster
;; but still not as fast as make-polar
(define go-fast? #true)
(define imag-func (if go-fast? make-polar make-rectangular))
(define (expand line)
(match-define (list x1 x2) (map real-part line))
(match-define (list y1 y2) (map imag-part line))
(cond
[(= x1 x2)
(for/list ([i (in-range (apply min (list y1 y2)) (add1 (apply max (list y1 y2))))])
(imag-func x1 i))]
[(= y1 y2)
(for/list ([i (in-range (apply min (list x1 x2)) (add1 (apply max (list x1 x2))))])
(imag-func i y1))]
[else (for/list ([x (in-range x1 ((if (> x1 x2) sub1 add1) x2) (if (> x1 x2) -1 1))]
[y (in-range y1 ((if (> y1 y2) sub1 add1) y2) (if (> y1 y2) -1 1))])
(imag-func x y))]))
(define (calc-result points)
(length (filter (λ (x) (>= x 2)) (hash-values (time (frequency-hash points))))))
(check-equal? (calc-result (append-map expand (filter Line-not-diagonal lines))) 6113)
(check-equal? (calc-result (append-map expand lines)) 20373)