Advent of Code '23 - day 16

Table of Contents

Part one involves once again, following a path without getting stuck in an endless loop. For part two my solution was to simple run the same code over and over again and deduce the answer, but it got rejected. I have a gut feeling this is due to to loop detection, which kicks in at the wrong moment and thus stopping a trace prematurely. Will look into this later.

Input

Example

.|...\....
|.-.\.....
.....|-...
........|.
..........
.........\
..../.\\..
.-.-/..|..
.|....-|.\
..//.|....

Part 1

  (defun aoc23/part-1 (input)
    (let ((stack (list (cons 0 '(1 . 0))))
      history
      h2
      (length (1+ (string-search "\n" input))))
      (while stack
        ;(message "> %S" stack)
        (let* ((cell (car stack))
           (next (aoc23/process-cell cell input length))
           (next (seq-filter (lambda (c)
                               (and (aoc23/valid-cell-p c input length)
                                    (not (member cell h2))))
                             next)))
      (setq history (cons (car cell) history))
      (setq h2 (cons cell h2))
      (if next
          (setq stack (append (cdr stack) next))
        (setq stack (cdr stack)))
      ))
      (seq-uniq (mapcar 'car h2))))

  (defun aoc23/valid-cell-p (cell input length)
    (let ((j (car cell)))
      (and (>= j 0)
       (< j (length input))
       (not (= (elt input j) ?\n)))))

  (defun aoc23/translate (i length vector)
    (+ i (car vector)
       (* length (cdr vector))))

  (defun aoc23/make-cell (i length vector)
    (cons (aoc23/translate i length vector) vector))

  (defun aoc23/process-cell (cell input length)
    (let* ((i (car cell))
       (vector (cdr cell))
       (c (elt input i)))
      (cond ((= c ?.)
         (list (aoc23/make-cell i length vector)))

        ((= 1 (abs (car vector)))
         (cond ((= c ?-)
                (list (aoc23/make-cell i length vector)))
               ((= c ?\\)
                (list (aoc23/make-cell i length (cons 0 (car vector)))))
               ((= c ?/)
                (list (aoc23/make-cell i length (cons 0 (* -1 (car vector))))))
               ((= c ?|)
                (list (aoc23/make-cell i length '(0 . -1))
                      (aoc23/make-cell i length '(0 . 1))))))

        ((= 1 (abs (cdr vector)))
         (cond ((= c ?|)
                (list (aoc23/make-cell i length vector)))
               ((= c ?/) 
                (list (aoc23/make-cell i length (cons (* -1 (cdr vector)) 0))))
               ((= c ?\\) 
                (list (aoc23/make-cell i length (cons (cdr vector) 0))))
               ((= c ?-)
                (list (aoc23/make-cell i length '(-1 . 0))
                      (aoc23/make-cell i length '(1 . 0)))))))))

(save-excursion 
  (let* ((m (aoc23/part-1 input))
         (answer (length m)))
    (switch-to-buffer-other-frame "*map*")
    (with-current-buffer "*map*"
      (erase-buffer)
      (dotimes (i (length input))
        (let ((c (char-to-string (elt input i))))
      (when (string= c "\n")
        (setq c (concat "$" c)))
        (when (member i m)
         (setq c (propertize c 'font-lock-face '(:foreground "red"))))
        (insert c))))
    (insert (format "\n\nanswer: %d" answer))))

Part 2