Solve puzzle 11 2022.
This commit is contained in:
116
2022/puzzle-11.lisp
Normal file
116
2022/puzzle-11.lisp
Normal file
@@ -0,0 +1,116 @@
|
||||
(load "lib")
|
||||
|
||||
(defparameter input (uiop:read-file-string "11-input"))
|
||||
(defparameter lines (get-lines input))
|
||||
|
||||
(defun lines->segments (lines)
|
||||
(--> (split-by-completely lines "" #'string=)
|
||||
(mapcar (lambda (x)
|
||||
(--> (loop for i in x
|
||||
collect
|
||||
(string-trim '(#\Space) i))))
|
||||
it)))
|
||||
|
||||
(defun segment->monkey (segment)
|
||||
(destructuring-bind (name starting op test clause-1 clause-2) segment
|
||||
(declare (ignore name))
|
||||
`(:items
|
||||
,(--> (subseq starting 16)
|
||||
(string-to-clist it)
|
||||
(split-by-completely it #\,)
|
||||
(mapcar (lambda (lst)
|
||||
(--> (clist-to-string lst)
|
||||
(string-trim '(#\Space) it)
|
||||
(parse-integer it)))
|
||||
it))
|
||||
:inspect
|
||||
,(--> (subseq op 21)
|
||||
(format nil "(~a old)" it)
|
||||
(with-input-from-string (s it)
|
||||
(read s))
|
||||
(eval `(lambda (old) ,it)))
|
||||
:test
|
||||
,(let ((test (parse-integer (subseq test 19)))
|
||||
(clause-1 (parse-integer (subseq clause-1 25)))
|
||||
(clause-2 (parse-integer (subseq clause-2 26))))
|
||||
(lambda (n)
|
||||
(if (= (mod n test) 0)
|
||||
clause-1
|
||||
clause-2)))
|
||||
:divisor ,(parse-integer (subseq test 19)))))
|
||||
|
||||
(defmacro get-monkey (monkeys ind)
|
||||
`(nth ,ind ,monkeys))
|
||||
|
||||
(defmacro get-monkey-items (monkeys ind)
|
||||
`(getf (get-monkey ,monkeys ,ind) :items))
|
||||
|
||||
(defun monkey-increment-alist (monkey-alist monkey-ind)
|
||||
(setf (cdr (assoc monkey-ind monkey-alist))
|
||||
(+ 1 (cdr (assoc monkey-ind monkey-alist)))))
|
||||
|
||||
(defun monkey-send-item (monkeys item recipient)
|
||||
(setf (get-monkey-items monkeys recipient)
|
||||
(append (get-monkey-items monkeys recipient)
|
||||
(list item))))
|
||||
|
||||
(defun monkey-process-item (inspect item)
|
||||
(floor (/ (funcall inspect item) 3)))
|
||||
|
||||
(defun monkey-do-turn (monkeys monkey-alist monkey-ind)
|
||||
(let* ((monkey (nth monkey-ind monkeys))
|
||||
(items (getf monkey :items))
|
||||
(inspect (getf monkey :inspect))
|
||||
(test (getf monkey :test)))
|
||||
(loop for item in items
|
||||
for proper-item = (monkey-process-item inspect item)
|
||||
for recipient = (funcall test proper-item)
|
||||
do (monkey-send-item monkeys proper-item recipient)
|
||||
do (monkey-increment-alist monkey-alist monkey-ind))
|
||||
(setf (get-monkey-items monkeys monkey-ind) nil)
|
||||
monkeys))
|
||||
|
||||
(defun monkeys-do-round (monkeys monkey-alist)
|
||||
(loop for monkey in monkeys
|
||||
for i from 0
|
||||
do (monkey-do-turn monkeys monkey-alist i)))
|
||||
|
||||
(defun monkey-business (monkey-alist)
|
||||
(--> (lambda (x y) (> (cdr x) (cdr y)))
|
||||
(sort monkey-alist it)
|
||||
(subseq it 0 2)
|
||||
(mapcar #'cdr it)
|
||||
(reduce #'* it)))
|
||||
|
||||
(let* ((monkeys (--> (lines->segments lines)
|
||||
(mapcar #'segment->monkey it)))
|
||||
(monkey-alist (loop for monkey in monkeys
|
||||
for i from 0
|
||||
collect `(,i . 0))))
|
||||
|
||||
(loop for i from 1 to 20
|
||||
do (monkeys-do-round monkeys monkey-alist))
|
||||
|
||||
(format t "Round 1: ~a~%" (monkey-business monkey-alist)))
|
||||
|
||||
(defvar *monkey-divisor* nil)
|
||||
|
||||
(defun monkey-process-item (inspect item)
|
||||
(mod (funcall inspect item) *monkey-divisor*))
|
||||
|
||||
(let* ((monkeys (--> (lines->segments lines)
|
||||
(mapcar #'segment->monkey it)))
|
||||
(monkey-alist (loop for monkey in monkeys
|
||||
for i from 0
|
||||
collect `(,i . 0))))
|
||||
|
||||
;; To ensure we don't go too hard.
|
||||
(setq *monkey-divisor* (reduce #'*
|
||||
(loop for monkey in monkeys
|
||||
for divisor = (getf monkey :divisor)
|
||||
collect divisor)))
|
||||
|
||||
(loop for i from 1 to 10000
|
||||
do (monkeys-do-round monkeys monkey-alist))
|
||||
|
||||
(format t "Round 2: ~a~%" (monkey-business monkey-alist)))
|
||||
Reference in New Issue
Block a user