~shunter/advent2021

19010b330e7847e473258c41641f8192c96b99fe — Samuel Hunter 2 years ago eff818e
Solve Day 12
2 files changed, 86 insertions(+), 0 deletions(-)

A day12.lisp
A input/day12.txt
A day12.lisp => day12.lisp +65 -0
@@ 0,0 1,65 @@
(defpackage #:advent2021.day12
  (:use #:cl #:alexandria #:cl-ppcre #:advent2021.util)
  (:export #:solve-part-1 #:solve-part-2))

(in-package #:advent2021.day12)



(defparameter +input+
  (loop :with map := (make-hash-table)
        :for line :in (parse-lines #'identity)
        :for (from to) := (mapcar (lambda (kw)
                                    (intern kw :keyword))
                                  (split "-" line))
        :do (push to (gethash from map))
            (push from (gethash to map))
        :finally (return map)))

(defun possible-paths (start &optional route)
  (cond
    ((eq start :|end|) 1)
    ((member start route) 0)
    (t
     (loop :for next-node :in (gethash start +input+)
           :sum (possible-paths next-node
                                (if (upper-case-p
                                      (char (string start) 0))
                                    route
                                    (cons start route)))))))

(defun solve-part-1 ()
  (possible-paths :|start|))

(defun large? (node)
  (upper-case-p (char (string node) 0)))

(defun cave-visited-twice? (route)
  (loop :with small-caves := ()
        :for cave :in route
        :do (when (not (large? cave))
              (if (member cave small-caves)
                  (return t)
                  (push cave small-caves)))))

(defun should-visit? (node route)
  (when (eq node :|start|)
      (return-from should-visit? nil))

  (or (large? node)
      (< (loop :for n :in route
            :count (eq n node))
         (if (cave-visited-twice? route)
             1 2))))

(defun possible-paths* (start &optional route)
  (cond
    ((eq start :|end|)
     ;; (print (list :path route))
     1)
    (t (loop :for next-node :in (gethash start +input+)
             :when (should-visit? next-node (cons start route))
             :sum (possible-paths* next-node (cons start route))))))

(defun solve-part-2 ()
  (possible-paths* :|start|))

A input/day12.txt => input/day12.txt +21 -0
@@ 0,0 1,21 @@
TR-start
xx-JT
xx-TR
hc-dd
ab-JT
hc-end
dd-JT
ab-dd
TR-ab
vh-xx
hc-JT
TR-vh
xx-start
hc-ME
vh-dd
JT-bm
end-ab
dd-xx
end-TR
hc-TR
start-vh