summaryrefslogtreecommitdiffstats
path: root/2021/12
diff options
context:
space:
mode:
Diffstat (limited to '2021/12')
-rw-r--r--2021/12/input23
-rw-r--r--2021/12/one.tl49
-rw-r--r--2021/12/testinput7
-rw-r--r--2021/12/two.tl68
4 files changed, 147 insertions, 0 deletions
diff --git a/2021/12/input b/2021/12/input
new file mode 100644
index 0000000..756681b
--- /dev/null
+++ b/2021/12/input
@@ -0,0 +1,23 @@
+pn-TY
+rp-ka
+az-aw
+al-IV
+pn-co
+end-rp
+aw-TY
+rp-pn
+al-rp
+end-al
+IV-co
+end-TM
+co-TY
+TY-ka
+aw-pn
+aw-IV
+pn-IV
+IV-ka
+TM-rp
+aw-PD
+start-IV
+start-co
+start-pn
diff --git a/2021/12/one.tl b/2021/12/one.tl
new file mode 100644
index 0000000..70e36d5
--- /dev/null
+++ b/2021/12/one.tl
@@ -0,0 +1,49 @@
+(defvar %cave-hash% (hash))
+
+(defstruct cave ()
+ name
+ neighbors
+
+ (:postinit (cv)
+ (assert cv.name)
+ (set [%cave-hash% cv.name] cv)))
+
+(defstruct small-cave cave
+ (:method visit (cv path fn)
+ (unless (member cv path)
+ (push cv path)
+ (each ((n cv.neighbors))
+ n.(visit path fn)))))
+
+(defstruct big-cave cave
+ (:method visit (cv path fn)
+ (push cv path)
+ (each ((n cv.neighbors))
+ n.(visit path fn))))
+
+(defstruct end-cave cave
+ (:method visit (cv path fn)
+ (push cv path)
+ [fn path]))
+
+(defun ensure-cave (name)
+ (or [%cave-hash% name]
+ (set [%cave-hash% name]
+ (match-case name
+ ("end" (new end-cave name name))
+ (@[all @str chr-islower] (new small-cave name name))
+ (@else (new big-cave name name))))))
+
+(defun read-caves (: (name "input"))
+ (with-stream (s (open-file name))
+ (whilet ((line (get-line s)))
+ (match `@a-@b` line
+ (let ((ca (ensure-cave a))
+ (cb (ensure-cave b)))
+ (pushnew cb ca.neighbors)
+ (pushnew ca cb.neighbors))))))
+
+(defun find-paths (fn)
+ (let ((start [%cave-hash% "start"]))
+ (assert start)
+ start.(visit nil fn)))
diff --git a/2021/12/testinput b/2021/12/testinput
new file mode 100644
index 0000000..6fd8c41
--- /dev/null
+++ b/2021/12/testinput
@@ -0,0 +1,7 @@
+start-A
+start-b
+A-c
+A-b
+b-d
+A-end
+b-end
diff --git a/2021/12/two.tl b/2021/12/two.tl
new file mode 100644
index 0000000..69f179a
--- /dev/null
+++ b/2021/12/two.tl
@@ -0,0 +1,68 @@
+(defvar %cave-hash% (hash))
+
+(defstruct cave ()
+ name
+ neighbors
+
+ (:postinit (cv)
+ (assert cv.name)
+ (set [%cave-hash% cv.name] cv)))
+
+(defstruct end-cave cave
+ (:method visit (cv path fn)
+ (push cv path)
+ [fn (remq t path)]))
+
+(defstruct start-cave cave
+ (:method visit (cv path fn)
+ (unless (member cv path)
+ (push cv path)
+ (each ((n cv.neighbors))
+ n.(visit path fn)))))
+
+(defstruct small-cave cave
+ (:method visit (cv path fn)
+ (let ((in-path (member cv path)))
+ (when (or (not in-path)
+ (not (member t path)))
+ (push cv path)
+ (if in-path
+ (push t path))
+ (each ((n cv.neighbors))
+ n.(visit path fn))))))
+
+(defstruct big-cave cave
+ (:method visit (cv path fn)
+ (push cv path)
+ (each ((n cv.neighbors))
+ n.(visit path fn))))
+
+(defun ensure-cave (name)
+ (or [%cave-hash% name]
+ (set [%cave-hash% name]
+ (match-case name
+ ("end" (new end-cave name name))
+ ("start" (new start-cave name name))
+ (@[all @str chr-islower] (new small-cave name name))
+ (@else (new big-cave name name))))))
+
+(defun read-caves (: (name "input"))
+ (with-stream (s (open-file name))
+ (whilet ((line (get-line s)))
+ (match `@a-@b` line
+ (let ((ca (ensure-cave a))
+ (cb (ensure-cave b)))
+ (pushnew cb ca.neighbors)
+ (pushnew ca cb.neighbors))))))
+
+(defun find-paths (fn)
+ (let ((start [%cave-hash% "start"]))
+ (assert start)
+ start.(visit nil fn)))
+
+(defun solve (: (name "input"))
+ (let (paths)
+ (read-caves name)
+ (find-paths (opip reverse (mapcar .name) (push @1 paths)))
+ (mapdo [chain (ap join-with ",") pprinl] paths)
+ (len paths)))