use complex numbers

2016
Matthew Butterick 7 years ago
parent 1d1c9d323b
commit 7d08926344

@ -11,54 +11,48 @@
(define-macro (mb NUM) (define-macro (mb NUM)
#'(#%module-begin #'(#%module-begin
(solve 50 NUM) (solve 50 NUM) ; 50 is arbitrarily large space to search
(solve2 NUM))) (solve2 NUM)))
(define starting-pt 1+1i)
(define (solve dim num) (define (solve dim num)
(define open? (make-open-pred num)) (define open? (make-open-pred num))
(define g (undirected-graph '((0 0)))) (define g (undirected-graph (list starting-pt)))
(for* ([y (in-range dim)] (for* ([row (in-range dim)]
[x (in-range dim)] [col (in-range dim)]
#:when (open? (cons x y))) [p (in-value (+ col (* +i row)))]
(when (open? (cons (add1 x) y)) #:when (open? p))
(add-edge! g (cons x y) (cons (add1 x) y))) (when (open? (+ p 1)) (add-edge! g p (+ p 1)))
(when (open? (cons x (add1 y))) (when (open? (+ p +i)) (add-edge! g p (+ p +i))))
(add-edge! g (cons x y) (cons x (add1 y))))) (define path (fewest-vertices-path g 1+1i 31+39i))
(define path (fewest-vertices-path g '(1 . 1) '(31 . 39)))
(displayln (and path (sub1 (length path))))) (displayln (and path (sub1 (length path)))))
(define (solve2 num) (define (solve2 num)
(define open? (make-open-pred num)) (define open? (make-open-pred num))
(define (nonnegative? pt) (and (not (negative? (car pt))) (define (nonnegative? pt) (and (not (negative? (real-part pt)))
(not (negative? (cdr pt))) (not (negative? (imag-part pt)))
pt)) pt))
(let loop ([all-visited-pts empty] (let take-step ([all-visited-pts empty]
[last-visited-pts '((1 . 1))] [last-visited-pts (list starting-pt)]
[step 0]) [count 0])
(cond (if (= count 50)
[(= step 50) (length (remove-duplicates (append all-visited-pts last-visited-pts)))
(length (remove-duplicates (append all-visited-pts last-visited-pts)))] (take-step
[else (append last-visited-pts all-visited-pts)
(loop (append last-visited-pts all-visited-pts) (flatten
(append* (for*/list ([p (in-list last-visited-pts)]
(for/list ([lvp (in-list last-visited-pts)]) [next-p (in-list (map (curry + p) '(1 -1 +i -i)))]
(match-define (cons x y) lvp) #:when (and (nonnegative? next-p)
(for/list ([pt (in-list (list (cons (add1 x) y) (open? next-p)
(cons x (add1 y)) (not (member next-p all-visited-pts))))
(cons (sub1 x) y) next-p))
(cons x (sub1 y))))] (add1 count)))))
#:when (and (nonnegative? pt)
(open? pt)
(not (member pt all-visited-pts))))
pt)))
(add1 step))])))
(define (make-open-pred num) (define (make-open-pred num)
(λ(pt) (λ(pt)
(match-define (cons x y) pt) (define col (real-part pt))
(define row (imag-part pt))
(define sum (define sum
(+ (* x x) (* 3 x) (* 2 x y) y (* y y) num)) (+ (* col col) (* 3 col) (* 2 col row) row (* row row) num))
(even? (even? (length (regexp-match* "1" (format "~b" sum))))))
(for/sum ([c (in-string (format "~b" sum))]
#:when (char=? #\1 c))
1))))