diff options
Diffstat (limited to 'AoC2023/day19')
-rw-r--r-- | AoC2023/day19/solver.lisp | 82 |
1 files changed, 38 insertions, 44 deletions
diff --git a/AoC2023/day19/solver.lisp b/AoC2023/day19/solver.lisp index b96f23f..7a95a71 100644 --- a/AoC2023/day19/solver.lisp +++ b/AoC2023/day19/solver.lisp @@ -18,15 +18,23 @@ :s (copy-tree s)))) (defun part-options (range-part) - (with-slots (x m a s) range-part - (reduce #'* - (list x m a s) - :key (lambda (v) - (destructuring-bind (st . end) v - (1+ (- end st))))))) + (reduce #'* '(x m a s) + :key (lambda (v) + (destructuring-bind (st . end) + (slot-value range-part v) + (1+ (- end st)))))) + +(defun parse-tests (line-rule) + (loop for test in (cl-ppcre:split "," line-rule) + collect + (cl-ppcre:register-groups-bind ((#'read-from-string prop op val target)) + ("\(\\w\)\(<|>\)\(\\d+\):\(\\w+\)" test) + (list op prop val target)))) (defun parse-rule (line) - (cl-ppcre:register-groups-bind ((#'read-from-string name) (#'parse-tests tests) (#'read-from-string default)) + (cl-ppcre:register-groups-bind ((#'read-from-string name) + (#'parse-tests tests) + (#'read-from-string default)) ("\(\\w+\){\(.*\),\(\\w+\)}" line) (list* name default tests))) @@ -44,42 +52,42 @@ (setf (gethash name workflows) rule))))) (values workflows parts))) +(defun test-part (workflows part &optional (start 'in)) + (destructuring-bind (default . tests) (gethash start workflows) + (let ((out (or (loop for (op prop val target) in tests + when (funcall op (slot-value part prop) val) + do (return target)) + default))) + (cond ((eq 'A out) + (part-sum part)) + ((eq 'R out) 0) + ((test-part workflows part out)))))) + (defun solve (filename) (multiple-value-bind (workflows parts) (parse-file filename) - (maphash (lambda (k v) - (destructuring-bind (default . tests) v - (setf (gethash k workflows) - (lambda (part) - (or (loop for (op prop val target) in tests - when (funcall op (slot-value part prop) val) - do (return target)) - default))))) - workflows) (reduce #'+ parts :key (alexandria:curry #'test-part workflows)))) -(defun parse-tests (line-rule) - (loop for test in (cl-ppcre:split "," line-rule) - collect - (cl-ppcre:register-groups-bind ((#'read-from-string prop op val target)) - ("\(\\w\)\(<|>\)\(\\d+\):\(\\w+\)" test) - (list op prop val target)))) +(defun final-options (solutions) + (loop for (r p) on solutions + by #'cddr + when (eq r 'A) + sum (part-options p))) (fiveam:test parts (fiveam:is (equal '((< S 537 GD) (> X 2440 R)) - (parse-tests "s<537:gd,x>2440:R" )))) + (parse-tests "s<537:gd,x>2440:R" ))) + (fiveam:is (= 256000000000000 + (final-options (list 'a + (make-part :x (cons 1 4000) + :m (cons 1 4000) + :a (cons 1 4000) + :s (cons 1 4000))))))) (fiveam:test solutions (fiveam:is (= 19114 (solve "eg-in"))) (fiveam:is (= 446517 (solve "input")))) -(defun test-part (workflows part &optional (start 'in)) - (let ((out (funcall (gethash start workflows) part))) - (cond ((eq 'A out) - (part-sum part)) - ((eq 'R out) 0) - ((test-part workflows part out))))) - (defun part-2 (workflows start range) (if (member start '(A R)) @@ -118,18 +126,4 @@ (fiveam:is (= 167409079868000 (solve2 "eg-in"))) (fiveam:is (= 130090458884662 (solve2 "input")))) -(defun final-options (solutions) - (loop for (r p) on solutions - by #'cddr - when (eq r 'A) - sum (part-options p))) - -(fiveam:test parts2 - (fiveam:is (= 256000000000000 - (final-options (list 'a - (make-part :x (cons 1 4000) - :m (cons 1 4000) - :a (cons 1 4000) - :s (cons 1 4000))))))) - (fiveam:run!) |