diff options
Diffstat (limited to 'AoC2022')
-rw-r--r-- | AoC2022/19/solver.lisp | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/AoC2022/19/solver.lisp b/AoC2022/19/solver.lisp index 0c67060..37b1e74 100644 --- a/AoC2022/19/solver.lisp +++ b/AoC2022/19/solver.lisp @@ -11,37 +11,23 @@ (defun parse-robot-recipe (line) (cl-ppcre:register-groups-bind ((#'material robot) (#'parse-integer fq) (#'material fm) (#'parse-integer sq) (#'material sm)) ("(\\w+) robot costs (\\d+) (\\w+)(?: and (\\d+) (\\w+))?" line) - (append - (list robot fm fq) - (when sm (list sm sq))))) + (let ((first-material (fset:with (fset:empty-bag) fm fq))) + (fset:map (robot + (if sm (fset:with first-material sm sq) + first-material)))))) -(defun start-resources () - (list :ore 0 :clay 0 :obsidian 0 :geode 0)) -(defun start-bots () - (list :ore 1 :clay 0 :obsidian 0 :geode 0)) (defun can-build-robot-p (requirements available) - (loop for (material amount) on requirements by #'cddr - always (<= amount (getf available material 0)))) + (fset:subbag? requirements available)) (defun consume (requirements available) - (loop for (material amount) on requirements by #'cddr - do (decf (getf available material) amount)) - available) - -(fiveam:test requirements - (fiveam:is-false (can-build-robot-p '(:ore 6) '(:ore 5))) - (fiveam:is-false (can-build-robot-p '(:ore 6) '(:clay 5))) - (fiveam:is-true (can-build-robot-p '(:ore 2) '(:ore 5))) - (fiveam:is-true (can-build-robot-p '(:ore 2) '(:clay 2 :ore 5))) - (fiveam:is (equal '(:ore 2) (consume '(:ore 3) '(:ore 5))))) + (fset:bag-difference available requirements)) (defun material-collect (bots available-materials) - (loop for (material amount) on bots by #'cddr - nconc (list material (+ (getf available-materials material 0) amount)))) + (fset:bag-sum bots available-materials)) (defun bot-requirements (type recipes) - (cdr (assoc type recipes :test #'eq))) + (fset:lookup recipes type)) (defun plist-merge (func p1 p2 &optional default) "Merge 2 flat plists P1 & P2 by FUNC. Use DEFAULT when value is missing on one list." @@ -70,22 +56,38 @@ (defun try! (build-next robots resources blueprints) (let ((req (bot-requirements build-next blueprints))) - (when (can-build-robot-p req resources) - (consume req resources) - (incf (getf robots build-next 0))))) - + (if (can-build-robot-p req resources) + (values + (consume req resources) + (fset:with robots build-next)) + (values resources robots)))) (defun next-step (build-next robots resources blueprints time-left) (if (zerop time-left) - (list robots resources) - (let ((new-robots (try! build-next robots resources blueprints))) - (mapcar - (lambda (next) - (next-step next robots (material-collect robots resources) blueprints (1- time-left))) - (if new-robots - (should-build blueprints robots) - (list build-next)))) - )) + ;; (list robots resources) + (fset:multiplicity resources :geode) + ;; resources + (let ((req (bot-requirements build-next blueprints))) + (if (can-build-robot-p req resources) + (reduce (lambda (max next) + (max max + (next-step next + (fset:with robots build-next) + (material-collect robots (consume req resources)) + blueprints (1- time-left)))) + '(:geode :obsidian :clay :ore) + :initial-value 0) + (next-step build-next + robots + (material-collect robots resources) + blueprints (1- time-left)))))) + +(defun start-resources () + ;; (list :ore 0 :clay 0 :obsidian 0 :geode 0) + (fset:empty-bag)) +(defun start-bots () + ;; (list :ore 1 :clay 0 :obsidian 0 :geode 0) + (fset:bag :ore)) (let ((blueprints (cdar @@ -93,16 +95,15 @@ (lambda (l) (let ((blueprint (uiop:split-string l :separator ":."))) (cons (car blueprint) - (mapcar #'parse-robot-recipe (butlast (cdr blueprint)))))) + (reduce #'fset:map-union + (mapcar #'parse-robot-recipe (butlast (cdr blueprint))))))) (uiop:read-file-lines "eg-in")))) ;; (materials '(:ore 8 :clay 20)) (materials (start-resources)) (bots (start-bots)) ;; (bots '(:geode 1 :ore 8 :clay 20)) - (time-left 5)) + (time-left 24)) (next-step :clay bots materials blueprints time-left) - - ) |