Advent-of-Code/day19.lisp

59 lines
2.1 KiB
Common Lisp

;; https://adventofcode.com/2022/day/19
(defpackage :day-19
(:use :cl))
(in-package :day-19)
(defparameter *all-types* '(:geode :obsidian :clay :ore))
(defclass state ()
((resources :accessor resources :initform nil :initarg :resources)
(robots :accessor robots :initform (list :ore 1) :initarg :robots)))
(defmethod print-object ((obj state) stream)
(print-unreadable-object (obj stream :type t)
(with-slots (resources robots)
obj
(format stream "collected: ~a, with robots: ~a"
resources robots))))
;; example of blueprint:
(defparameter *test-blueprint*
'(:id 1
:ore (:ore 4)
:clay (:ore 2)
:obsidian (:ore 3 :clay 14)
:geode (:ore 2 :obsidian 7)))
;; thank you blambert & stackoverflow
;; https://stackoverflow.com/questions/11067899/is-there-a-generic-method-for-cloning-clos-objects
;; oh, but this is shallow copy and lists reused. crap
(defmethod copy-state ((s state))
(make-instance 'state :resources (copy-list (resources s))
:robots (copy-list (robots s))))
(defmethod can-create-robot (blueprints type (s state))
(let ((this-robot-costs (getf blueprints type)))
(loop for (resource amount) on this-robot-costs by #'cddr
always (>= (getf (resources s) resource 0) amount))))
(defmethod create-robot (blueprints type (s state))
(when (can-create-robot blueprints type s)
(let ((this-robot-costs (getf blueprints type))
(copied-state (copy-state s)))
(loop for (resource amount) on this-robot-costs by #'cddr
do (incf (getf (resources copied-state) resource 0) (- amount)))
(incf (getf (robots copied-state) type 0))
copied-state)))
(defmethod calc-resources-to-be-collected ((s state))
(robots s))
(defmethod add-resources (new-resources (s state))
(loop for (resource amount) on new-resources by #'cddr
do (incf (getf (resources s) resource 0) amount)))
(defmethod get-possible-bot-builds (blueprints (s state))
(remove-if-not (lambda (robot-type) (can-create-robot blueprints robot-type s))
*all-types*))