Advent of Code '23 - day 10

Table of Contents

The first part was pretty straightforward, following a path till we reach our starting position. I skipped the second part for the time being.

Input

Examples

7-F7-
.FJ|7
SJLL7
|F--J
LJ.LJ
.....
.S-7.
.|.|.
.L-J.
.....

Part 1

(defun aoc23/parse-input (string)
  (let ((map (string-split string "\n" t))
        (m (make-hash-table :test 'equal)))
    (puthash "map" map m)
    (puthash "h" (length map) m)
    (puthash "w" (length (car map)) m)
    m))

(defun aoc23/--node-at (p map)
  (elt (elt (gethash "map" map) (cdr p)) (car p)))

(defun aoc23/translate (p translation)
  (cons (+ (car p) (car translation)) (+ (cdr p) (cdr translation))))

(defun aoc23/exits-at (p map)
  (let ((c (aoc23/node-at p map))
        (x (car p))
        (y (cdr p)))
    (cond ((= c ?.)
           nil)
          ((= c ?J)
           (list (aoc23/translate p '(0 . -1))
                 (aoc23/translate p '(-1 . 0))))
          ((= c ?L)
           (list (aoc23/translate p '(0 . -1))
                 (aoc23/translate p '(1 . 0))))
          ((= c ?7)
           (list (aoc23/translate p '(0 . 1))
                 (aoc23/translate p '(-1 . 0))))
          ((= c ?F)
           (list (aoc23/translate p '(0 . 1))
                 (aoc23/translate p '(1 . 0))))
          ((= c ?-)
           (list (aoc23/translate p '(-1 . 0))
                 (aoc23/translate p '(1 . 0))))
          ((= c ?|)
           (list (aoc23/translate p '(0 . -1))
                 (aoc23/translate p '(0 . 1))))
          ((= c ?S)
           (list (aoc23/translate p '(0 . -1))
                 (aoc23/translate p '(0 . 1))
                 (aoc23/translate p '(-1 . 0))
                 (aoc23/translate p '(1 . 0)))))))

(defun aoc23/find-start (map)
  (let* ((w (1+ (gethash "w" map)))
         (m (apply 'concat (gethash "map" map)))
         (p (string-search "S" m))
         (y (/ p w))
         (x (% p w)))
    (cons x y)))

(defun aoc23/stop-search-p (nodes)
  (let ((cars (mapcar 'car nodes)))
    (and (length> cars 1)
         (length= (seq-filter (lambda (n)
                           (equal n (car cars)))
                              cars)
                  (length nodes)))))

(defun aoc23/valid-node-p (node map)
  (let ((h (gethash "h" map))
        (w (gethash "w" map))
        (x (car node))
        (y (cdr node)))
    (and (>= y 0)
         (< y h)
         (>= x 0)
         (< x w)
         (not (= (aoc23/--node-at node map) ?.)))))

(defun aoc23/node-at (p map)
  (when (aoc23/valid-node-p p map)
    (aoc23/--node-at p map)))

(let* ((map (aoc23/parse-input input))
       (startp (aoc23/find-start map))
       (current (list (cons startp nil)))
       (seen (list startp))
       (steps 0))
  (while current
    (let ((nnodes '()))
      (dolist (c current)
        (let* ((cn (car c))
               (m (aoc23/exits-at cn map))
               (m (seq-filter (lambda (c) (aoc23/valid-node-p c map)) m))
               (newexits (seq-difference m seen))
               (newexits (take 1 newexits))
               (newnodes (mapcar (lambda (n) (cons n c)) newexits)))
          (setq nnodes (append nnodes  newnodes))))
      (setq current nnodes)
      (setq seen (append seen (mapcar 'car current))))
    (setq steps (1+ steps)))
  (/ steps 2))

Part 2