aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2022/Day11/part-one.cl23
-rw-r--r--2022/Day11/part-two.cl109
2 files changed, 119 insertions, 13 deletions
diff --git a/2022/Day11/part-one.cl b/2022/Day11/part-one.cl
index 29f5b93..afab3ed 100644
--- a/2022/Day11/part-one.cl
+++ b/2022/Day11/part-one.cl
@@ -35,22 +35,19 @@
(push-back (pop (monkey-items m)) (monkey-items monkey-true))
(push-back (pop (monkey-items m)) (monkey-items monkey-false))))
-(defun create-operation-function (inpt)
- (eval `(lambda (old) (funcall ,(if (char= (char inpt 23) #\*) ; In the input, there is only * and +
- #'*
- #'+)
- old
- ,(if (char= (char inpt 25) #\o)
- 'old
- (parse-integer inpt :start 25))))))
-(defun create-test-function (inpt)
- (eval `(lambda (worry-level)
- (zerop (% worry-level ,(parse-integer inpt :start 21)))))) ; In the input we only test for divisibility
(ask-for-stream (prog-input)
(let ((monkeys '()) (buffer-items '()) (buffer-operation NIL) (buffer-test NIL) (buffer-throw-t -1) (buffer-throw-f -1))
-
+ (flet ((create-operation-function (inpt)
+ (eval `(lambda (old) (funcall ,(if (char= (char inpt 23) #\*) #'* #'+) ; In the input, there is only * and +
+ old
+ ,(if (char= (char inpt 25) #\o)
+ 'old
+ (parse-integer inpt :start 25))))))
+ (create-test-function (inpt)
+ (eval `(lambda (worry-level)
+ (zerop (% worry-level ,(parse-integer inpt :start 21))))))) ; In the input we only test for divisibility
(doread-lines (inpt :read-line-options (prog-input NIL))
(cond ((zerop (length inpt))) ; Do nothing on empty lines
@@ -98,4 +95,4 @@
if (< (monkey-inspections m) biggest)
maximize (monkey-inspections m) into second-biggest
finally
- (print (* biggest second-biggest))))))
+ (print (* biggest second-biggest)))))))
diff --git a/2022/Day11/part-two.cl b/2022/Day11/part-two.cl
new file mode 100644
index 0000000..362be8b
--- /dev/null
+++ b/2022/Day11/part-two.cl
@@ -0,0 +1,109 @@
+;;; https://gitlab.com/Syndamia/senzill
+(require :senzill)
+(use-package :senzill.math)
+(use-package :senzill.collections)
+(use-package :senzill.io)
+
+(defparameter +rounds+ 10000)
+
+(defclass monkey ()
+ ((items :initarg :items
+ :accessor monkey-items)
+ (inspections :initarg :inspections
+ :accessor monkey-inspections)
+ (operation :initarg :operation
+ :reader monkey-operation)
+ (test :initarg :test
+ :reader monkey-test)
+ (throw-true :initarg :throw-true
+ :reader monkey-throw-true)
+ (throw-false :initarg :throw-false
+ :reader monkey-throw-false))
+ (:default-initargs
+ :items '()
+ :inspections 0
+ :operation (lambda (old) old)
+ :test (lambda (worry-level) worry-level)
+ :throw-true 0
+ :throw-false 0))
+
+(defmethod inspect-and-throw ((m monkey) (monkey-true monkey) (monkey-false monkey) (modder integer))
+ (setf (first (monkey-items m))
+ (% (funcall (monkey-operation m) (first (monkey-items m))) modder))
+ (++1 (monkey-inspections m))
+ (if (funcall (monkey-test m) (first (monkey-items m)))
+ (push-back (pop (monkey-items m)) (monkey-items monkey-true))
+ (push-back (pop (monkey-items m)) (monkey-items monkey-false))))
+
+
+
+(ask-for-stream (prog-input)
+ (let ((monkeys '()) (modder 1) (buffer-items '()) (buffer-operation NIL) (buffer-test NIL) (buffer-throw-t -1) (buffer-throw-f -1))
+ (flet ((create-operation-function (inpt)
+ (eval `(lambda (old) (funcall ,(if (char= (char inpt 23) #\*) #'* #'+) ; In the input, there is only * and +
+ old
+ ,(if (char= (char inpt 25) #\o)
+ 'old
+ (parse-integer inpt :start 25))))))
+ (create-test-function (inpt)
+ (eval `(lambda (worry-level)
+ (zerop (% worry-level ,(parse-integer inpt :start 21))))))) ; In the input we only test for divisibility
+
+
+ (doread-lines (inpt :read-line-options (prog-input NIL))
+ (cond ((zerop (length inpt))) ; Do nothing on empty lines
+ ((char= (char inpt 0) #\M) ; Monkey #:
+ (push-back (make-instance 'monkey :items buffer-items
+ :operation buffer-operation
+ :test buffer-test
+ :throw-true buffer-throw-t
+ :throw-false buffer-throw-f)
+ monkeys))
+ ((char= (char inpt 2) #\S) ; Starting items:
+ (setf buffer-items (loop for itms = (subseq inpt 18) then (subseq itms (+ 2 (position #\, itms)))
+ collect (parse-integer itms :junk-allowed T)
+ while (position #\, itms))))
+ ((char= (char inpt 2) #\O) ; Operation:
+ (setf buffer-operation (create-operation-function inpt)))
+ ((char= (char inpt 2) #\T) ; Test:
+ ;; If we had one monkey, we could just mod the worry level, this way we
+ ;; reduce the number by not changing the outcome of the Test
+ ;; For two or more monkeys, we want this property to hold, so we need
+ ;; our number to be divisible by all the Test values, hence we mod
+ ;; by a number, divisible by all of those values.
+ ;; The smallest such number is the multiplication of all of those values.
+ ;; I was 99.99% there on figuring it out, but I still needed to look.
+ ;; Thanks https://github.com/arcogelderblom/AdventOfCode2022/
+ (*= modder (parse-integer inpt :start 21))
+ (setf buffer-test (create-test-function inpt)))
+ ((char= (char inpt 7) #\t) ; If true:
+ (setf buffer-throw-t (parse-integer inpt :start 29)))
+ ((char= (char inpt 7) #\f) ; If false:
+ (setf buffer-throw-f (parse-integer inpt :start 30)))))
+ ;; On very first line we add a monkey with default buffer values
+ (pop monkeys)
+ ;; The loop doesn't add the last monkey, since there is no new "Monkey #:" line
+ (push-back (make-instance 'monkey :items buffer-items
+ :operation buffer-operation
+ :test buffer-test
+ :throw-true buffer-throw-t
+ :throw-false buffer-throw-f)
+ monkeys)
+
+ (dotimes (r +rounds+)
+ (loop for m in monkeys
+ do (loop for item in (monkey-items m)
+ do (inspect-and-throw m
+ (nth (monkey-throw-true m) monkeys)
+ (nth (monkey-throw-false m) monkeys)
+ modder))))
+
+ (loop for m in monkeys
+ maximize (monkey-inspections m) into biggest
+ finally
+ ;;; This loop is unnecessary, inefficient and stupid, but I'm extra lazy today
+ (loop for m in monkeys
+ if (< (monkey-inspections m) biggest)
+ maximize (monkey-inspections m) into second-biggest
+ finally
+ (print (* biggest second-biggest)))))))