diff options
-rw-r--r-- | AoC2023/day12/solver.lisp | 40 |
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))) |