#+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