From 8eb6f9a713c7b7175eedf8d833493036a4c7d333 Mon Sep 17 00:00:00 2001 From: Syndamia Date: Sun, 11 Dec 2022 20:28:35 +0200 Subject: [2022/D11] Solved second part and reworked a bit first part of today's task --- 2022/Day11/part-one.cl | 23 +++++------ 2022/Day11/part-two.cl | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 2022/Day11/part-two.cl 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))))))) -- cgit v1.2.3