day11.lisp (3705B)
1 (defpackage #:adventofcode2022/day11 2 (:use #:cl #:adventofcode2022)) 3 (in-package #:adventofcode2022/day11) 4 5 (defclass monkey () 6 ((items :initform nil 7 :accessor items) 8 (operation-fun :accessor operation-fun) 9 (test-value :accessor test-value) 10 (test-fun :accessor test-fun) 11 (inspection-count :initform 0 12 :accessor inspection-count))) 13 14 (defun parse-monkeys (inputs) 15 (loop with monkeys = nil 16 with current-monkey = nil 17 with test-if-true = nil 18 for input in inputs 19 do (cond 20 ((str:starts-with-p "Monkey " input) 21 (setf current-monkey (make-instance 'monkey)) 22 (push current-monkey monkeys)) 23 ((str:starts-with-p " Starting items:" input) 24 (setf (items current-monkey) 25 (mapcar #'parse-integer 26 (str:split ", " (subseq input 18))))) 27 ((str:starts-with-p " Operation:" input) 28 (setf (operation-fun current-monkey) 29 (eval (read-from-string 30 (format nil "(lambda (old) (~A old))" (subseq input 23)))))) 31 ((str:starts-with-p " Test: divisible by" input) 32 (setf (test-value current-monkey) (parse-integer (subseq input 21)))) 33 ((str:starts-with-p " If true: throw to monkey" input) 34 (setf test-if-true (parse-integer (subseq input 29)))) 35 ((str:starts-with-p " If false: throw to monkey" input) 36 (setf (test-fun current-monkey) 37 (eval `(lambda (item) 38 (if (= (mod item ,(test-value current-monkey)) 0) 39 ,test-if-true 40 ,(parse-integer (subseq input 29)))))))) 41 finally (return (coerce (reverse monkeys) 'vector)))) 42 43 (defun let-monkeys-play (monkeys rounds &optional do-not-manage-worry-level?) 44 (loop 45 with test-value-product = (if do-not-manage-worry-level? 46 (apply #'* (map 'list #'test-value monkeys)) 47 0) 48 repeat rounds 49 do (loop for monkey across monkeys 50 do (loop with operation-fun = (operation-fun monkey) 51 with test-fun = (test-fun monkey) 52 for item in (items monkey) 53 for new-item = (let ((new-value (funcall operation-fun item))) 54 (if do-not-manage-worry-level? 55 (mod new-value test-value-product) 56 (floor (/ new-value 3)))) 57 for next-monkey-index = (funcall test-fun new-item) 58 for next-monkey = (aref monkeys next-monkey-index) 59 do (incf (inspection-count monkey)) 60 do (setf (items next-monkey) 61 (append (items next-monkey) (list new-item)))) 62 do (setf (items monkey) nil)))) 63 64 (defun get-monkey-business (monkeys) 65 (apply #'* 66 (map 'list 67 #'inspection-count 68 (subseq (sort monkeys 69 (lambda (monkey-1 monkey-2) 70 (> (inspection-count monkey-1) 71 (inspection-count monkey-2)))) 72 0 2)))) 73 74 (defun task1 (inputs) 75 (let ((monkeys (parse-monkeys inputs))) 76 (let-monkeys-play monkeys 20) 77 (get-monkey-business monkeys))) 78 79 (defun task2 (inputs) 80 (let ((monkeys (parse-monkeys inputs))) 81 (let-monkeys-play monkeys 10000 t) 82 (get-monkey-business monkeys))) 83 84 (define-day 11 85 () 86 #'task1 87 #'task2)