You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.8 KiB
100 lines
2.8 KiB
#+title: Solution to p7 |
|
|
|
Yay, another 2D problem |
|
#+begin_src emacs-lisp :results none |
|
(with-temp-buffer |
|
(insert-file-contents "input") |
|
(advent/replace-multiple-regex-buffer |
|
'(("^\\(.*\\)$" . "\"\\1\" "))) |
|
(goto-char (point-min)) |
|
(insert "(setq data '(") |
|
(goto-char (point-max)) |
|
(insert "))") |
|
(eval-buffer)) |
|
|
|
(setq data-char (-map #'advent/split-string-into-char-list data) |
|
width (length (car data-char)) |
|
height (length data-char)) |
|
#+end_src |
|
|
|
This is for part 1; record the splitting points and count them at the end |
|
#+begin_src emacs-lisp |
|
(defun position-valid-p (pos) |
|
(and (>= (car pos) 0) (< (car pos) width) |
|
(>= (cadr pos) 0) (< (cadr pos) height))) |
|
|
|
(defun tachyon-step (el) |
|
(if (not (position-valid-p el)) (list el) |
|
(let ((down (advent/neighbour el '(0 1)))) |
|
(if (or (not (position-valid-p down)) |
|
(not (eq ?^ (advent/char-at down data-char)))) |
|
(list down) |
|
(push down splits) |
|
(--map (advent/neighbour el it) '((-1 0) (1 0))))))) |
|
|
|
|
|
(setq tachyons (advent/coordinates-of ?S data-char) |
|
splits nil) |
|
(--fix (-distinct (-mapcat 'tachyon-step it)) tachyons) |
|
(length (-distinct splits)) |
|
#+end_src |
|
|
|
#+RESULTS: |
|
: 1507 |
|
|
|
This is for part 2. At each step record how many beams are at a given |
|
position. Each beam has some multiplicity. ~compress~ merges beams at |
|
the same position in one beam with multiplicity equal to the sum of |
|
the multiplicities of each beam |
|
#+begin_src emacs-lisp |
|
(defun tachyon-step-freq (el) |
|
(--map (cons it (cdr el)) |
|
(tachyon-step (car el)))) |
|
|
|
(setq tachyons (cons (car (advent/coordinates-of ?S data-char)) 1)) |
|
|
|
(defun compress (li) |
|
(--map (cons it (-sum (-map #'cdr |
|
(-filter (lambda (x) |
|
(equal it (car x))) |
|
li)))) |
|
(-distinct (-map #'car li)))) |
|
|
|
(-sum (-map #'cdr |
|
(--fix (compress (-mapcat 'tachyon-step-freq it)) |
|
(list tachyons)))) |
|
#+end_src |
|
|
|
#+RESULTS: |
|
: 1537373473728 |
|
|
|
now try part2 with a recursive approach. This should look better. |
|
Of course it will blow in my face if I did not cache the results |
|
(took 1.1s on Pixel 7) |
|
#+begin_src emacs-lisp |
|
(setq max-lisp-eval-depth 10000000) ; burn baby burn |
|
(setq cache nil) |
|
(defun cache-result (fun &rest r) |
|
(let ((c (assoc (cons fun r) cache))) |
|
(if c (cdr c) |
|
(let ((res (apply fun r))) |
|
(push (cons (cons fun r) res) cache) |
|
res )))) |
|
|
|
(advice-add 'timelines-at :around 'cache-result) |
|
|
|
(defun timelines-at (pos) |
|
(if (not (position-valid-p pos)) 1 |
|
(if (not (eq ?^ (advent/char-at pos data-char))) |
|
(timelines-at (advent/neighbour pos '(0 1))) |
|
(-sum (--map (timelines-at (advent/neighbour pos it)) |
|
'((1 0) (-1 0))))))) |
|
|
|
(setq tachyons (car (advent/coordinates-of ?S data-char))) |
|
(timelines-at tachyons) |
|
#+end_src |
|
|
|
#+RESULTS: |
|
: 1537373473728 |
|
|
|
|
|
|