diff options
Diffstat (limited to 'AoC2023/day19/solver.lisp')
-rw-r--r-- | AoC2023/day19/solver.lisp | 73 |
1 files changed, 32 insertions, 41 deletions
diff --git a/AoC2023/day19/solver.lisp b/AoC2023/day19/solver.lisp index 98bfd64..b96f23f 100644 --- a/AoC2023/day19/solver.lisp +++ b/AoC2023/day19/solver.lisp @@ -25,19 +25,36 @@ (destructuring-bind (st . end) v (1+ (- end st))))))) -(defun solve (filename) +(defun parse-rule (line) + (cl-ppcre:register-groups-bind ((#'read-from-string name) (#'parse-tests tests) (#'read-from-string default)) + ("\(\\w+\){\(.*\),\(\\w+\)}" line) + (list* name default tests))) + +(defun parse-file (filename) (let ((workflows (make-hash-table)) parts) - (loop for line in (uiop:read-file-lines filename) - do - (cond - ((string-equal line "")) - ((eq #\{ (aref line 0)) - (cl-ppcre:register-groups-bind ((#'parse-integer x m a s)) - ("{x=\(\\d+\),m=\(\\d+\),a=\(\\d+\),s=\(\\d+\)}" line) - (push (make-part :x x :m m :a a :s s) parts))) - ((multiple-value-bind (name rule) (parse-rule line) - (setf (gethash name workflows) rule))))) + (dolist (line (uiop:read-file-lines filename)) + (cond + ((string-equal line "")) + ((eq #\{ (aref line 0)) + (cl-ppcre:register-groups-bind ((#'parse-integer x m a s)) + ("{x=\(\\d+\),m=\(\\d+\),a=\(\\d+\),s=\(\\d+\)}" line) + (push (make-part :x x :m m :a a :s s) parts))) + ((destructuring-bind (name . rule) (parse-rule line) + (setf (gethash name workflows) rule))))) + (values workflows parts))) + +(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) @@ -56,16 +73,6 @@ (fiveam:is (= 19114 (solve "eg-in"))) (fiveam:is (= 446517 (solve "input")))) -(defun parse-rule (line) - (cl-ppcre:register-groups-bind ((#'read-from-string name) (#'parse-tests tests) (#'read-from-string default)) - ("\(\\w+\){\(.*\),\(\\w+\)}" line) - (values name - (lambda (part) - (or (loop for (op prop val target) in tests - when (funcall op (slot-value part prop) val) - do (return target)) - default))))) - (defun test-part (workflows part &optional (start 'in)) (let ((out (funcall (gethash start workflows) part))) (cond ((eq 'A out) @@ -77,7 +84,7 @@ (defun part-2 (workflows start range) (if (member start '(A R)) (list start range) - (destructuring-bind (df . opts) (cdr (assoc start workflows)) + (destructuring-bind (df . opts) (gethash start workflows) (let ((drops (loop for (op prop val target) in opts append (destructuring-bind (st . end) (slot-value range prop) @@ -93,28 +100,12 @@ (t (let ((rt (copy-part range))) (setf (slot-value range prop) (cons st val) (slot-value rt prop) (cons (1+ val) end)) - (part-2 workflows target rt))))) - - - )))) + (part-2 workflows target rt))))))))) - (append - (part-2 workflows df range) - drops - ))))) + (append (part-2 workflows df range) drops))))) (defun solve2 (filename) - (let ((workflows)) - (loop for line in (uiop:read-file-lines filename) - do - (unless (or (string-equal line "") (eq #\{ (aref line 0))) - (cl-ppcre:register-groups-bind ((#'read-from-string name) (#'parse-tests tests) (#'read-from-string default)) - ("\(\\w+\){\(.*\),\(\\w+\)}" line) - (push - (list* name default tests ) - - workflows)))) - ;; workflows + (let ((workflows (parse-file filename))) (final-options (part-2 workflows 'in (make-part :x (cons 1 4000) |