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

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