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.

2.8 KiB

Solution to p7

Yay, another 2D problem

  (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))

This is for part 1; record the splitting points and count them at the end

  (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))
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

  (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))))
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)

  (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)
1537373473728