aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AoC2023/day12/solver.lisp40
1 files changed, 40 insertions, 0 deletions
diff --git a/AoC2023/day12/solver.lisp b/AoC2023/day12/solver.lisp
new file mode 100644
index 0000000..ce196c9
--- /dev/null
+++ b/AoC2023/day12/solver.lisp
@@ -0,0 +1,40 @@
+(ql:quickload '(fiveam str arrows))
+
+(defparameter damaged #\#)
+(defparameter operational #\.)
+(defparameter unknown #\?)
+
+(defparameter eg-input "???.### 1,1,3
+.??..??...?##. 1,1,3
+?#?#?#?#?#?#?#? 1,3,1,6
+????.#...#... 4,1,1
+????.######..#####. 1,6,5
+?###???????? 3,2,1")
+
+
+(destructuring-bind (row . damage-list)
+ (cl-ppcre:split "[\\s,]" "???.###. 1,1,3")
+ (setf damage-list (mapcar #'parse-integer damage-list))
+ (labels ((options (row-idx damage-group)
+ (cond
+ ;; commited to all options
+ ((= damage-group (length damage-list))
+ ;; If still damaged springs are left, then
+ ;; it was a wrong arrangement, otherwise counts
+ (if (find damaged (subseq row row-idx)) 0 1))
+ ;; Not enough space to fit the current damaged-group
+ ((<= (length row) (+ row-idx (elt damage-list damage-group))) 0)
+ ;; Probe options. Either commit to a damage-group at row-idx or skip position
+ (t
+ (let* ((damaged-count (elt damage-list damage-group))
+ (next-slot (+ row-idx damaged-count)))
+ (+ (if (not (or (find operational (subseq row row-idx next-slot))
+ (char-equal damaged (aref row next-slot))))
+ ;; commits to the damage group, because in condition it has space
+ ;; Skips one slot, because it checked that it wasn't damaged
+ (options (1+ next-slot) (1+ damage-group))
+ 0)
+ (if (not (char-equal damaged (aref row row-idx)))
+ (options (1+ row-idx) damage-group)
+ 0)))))))
+ (options 0 0)))