aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day19/solver.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2023/day19/solver.lisp')
-rw-r--r--AoC2023/day19/solver.lisp73
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)