aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AoC2022/19/solver.lisp79
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)
-
-
)