|
|
|
|
@ -18,70 +18,66 @@ First parse with regex to make into a list |
|
|
|
|
end-pos (list (- width 1) (- height 1))) |
|
|
|
|
(setq full-data data) |
|
|
|
|
#+end_src |
|
|
|
|
now declare the usual helper functions |
|
|
|
|
Now define the usual helper functions |
|
|
|
|
#+begin_src emacs-lisp :results none |
|
|
|
|
(defun neighbour (p dir) |
|
|
|
|
"Returns the neighbour to P in the direction DIR" |
|
|
|
|
(list (+ (car p) (car dir)) |
|
|
|
|
(+ (cadr p) (cadr dir)))) |
|
|
|
|
(defun neighbour (p dir) |
|
|
|
|
"Returns the neighbour to P in the direction DIR" |
|
|
|
|
(list (+ (car p) (car dir)) |
|
|
|
|
(+ (cadr p) (cadr dir)))) |
|
|
|
|
|
|
|
|
|
(defun within-bounds-p (p) |
|
|
|
|
(let ((x (car p)) |
|
|
|
|
(y (cadr p))) |
|
|
|
|
(and (>= x 0) (< x width) |
|
|
|
|
(>= y 0) (< y height)))) |
|
|
|
|
(defun within-bounds-p (p) |
|
|
|
|
(let ((x (car p)) |
|
|
|
|
(y (cadr p))) |
|
|
|
|
(and (>= x 0) (< x width) |
|
|
|
|
(>= y 0) (< y height)))) |
|
|
|
|
|
|
|
|
|
(defun corrupted-p (p) |
|
|
|
|
(-contains-p data p)) |
|
|
|
|
(defun corrupted-p (p) |
|
|
|
|
(-contains-p data p)) |
|
|
|
|
|
|
|
|
|
(defun visited-p (p) |
|
|
|
|
(-contains-p (-map #'car distances) p)) |
|
|
|
|
(defun visited-p (p) |
|
|
|
|
(-contains-p (-map #'car distances) p)) |
|
|
|
|
|
|
|
|
|
(defun admissible-p (p) |
|
|
|
|
(and (within-bounds-p p) |
|
|
|
|
(not (corrupted-p p)) |
|
|
|
|
(not (visited-p p)))) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Define a generic bisect function |
|
|
|
|
#+begin_src emacs-lisp :results none |
|
|
|
|
(defun bisect (pred begin end) |
|
|
|
|
"returns the first n between BEGIN and END such that PRED n is nil" |
|
|
|
|
(if (eq (1+ begin) end) end |
|
|
|
|
(let ((mid (/ (+ begin end) 2))) |
|
|
|
|
(if (funcall pred mid) (bisect pred mid end) |
|
|
|
|
(bisect pred begin mid))))) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
Now solve the problem |
|
|
|
|
#+begin_src emacs-lisp |
|
|
|
|
(defun step (new-distances) |
|
|
|
|
(let ((radius (1+ (cdar new-distances))) |
|
|
|
|
(sphere (-map #'car new-distances))) |
|
|
|
|
(--map (cons it radius) (-filter #'admissible-p (-distinct (-mapcat (lambda (p) (--map (neighbour p it) ' ((1 0) (0 1) (-1 0) (0 -1)))) |
|
|
|
|
sphere)))))) |
|
|
|
|
(defun step (new-distances) |
|
|
|
|
(let ((radius (1+ (cdar new-distances))) |
|
|
|
|
(sphere (-map #'car new-distances))) |
|
|
|
|
(--map (cons it radius) (-filter #'admissible-p (-distinct (-mapcat (lambda (p) (--map (neighbour p it) ' ((1 0) (0 1) (-1 0) (0 -1)))) |
|
|
|
|
sphere)))))) |
|
|
|
|
|
|
|
|
|
(defun out-p (n) |
|
|
|
|
(setq data (-take n full-data) |
|
|
|
|
distances '(((0 0) . 0))) |
|
|
|
|
(setq new distances) |
|
|
|
|
(let* ((data (-take n full-data)) |
|
|
|
|
(distances '(((0 0) . 0))) |
|
|
|
|
(new distances)) |
|
|
|
|
|
|
|
|
|
(while (setq nn (step new)) |
|
|
|
|
(setq distances (-concat nn distances) |
|
|
|
|
new nn)) |
|
|
|
|
(assoc end-pos distances)) |
|
|
|
|
(nth (- (bisect 'out-p 1024 (length full-data)) 1) full-data) |
|
|
|
|
(while (setq new (step new)) |
|
|
|
|
(setq distances (-concat new distances))) |
|
|
|
|
(assoc end-pos distances))) |
|
|
|
|
|
|
|
|
|
;for part 1 |
|
|
|
|
(out-p 1024) |
|
|
|
|
|
|
|
|
|
;for part 2 |
|
|
|
|
(nth (- (bisect 'out-p 1024 (length full-data)) 1) full-data) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
#+RESULTS: |
|
|
|
|
| 10 | 38 | |
|
|
|
|
|
|
|
|
|
#+begin_src emacs-lisp |
|
|
|
|
(defun bisect (pred begin end) |
|
|
|
|
(if (eq (1+ begin) end) end |
|
|
|
|
(let ((mid (/ (+ begin end) 2))) |
|
|
|
|
(if (funcall pred mid) (bisect pred mid end) |
|
|
|
|
(bisect pred begin mid)))) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
(defun ddd (x) |
|
|
|
|
(< x 138)) |
|
|
|
|
|
|
|
|
|
(bisect 'ddd 10 1000) |
|
|
|
|
#+end_src |
|
|
|
|
|
|
|
|
|
#+RESULTS: |
|
|
|
|
: 138 |
|
|
|
|
|
|
|
|
|
|