commit d44443aadb80359e6113267856399cc001301e9b
parent 7d6cf65c3785908168567a2da695ac3d8e14fc1a
Author: Lukas Henkel <lh@entf.net>
Date: Sun, 11 Dec 2022 14:02:12 +0100
Day 11 task 1
Diffstat:
A | input/day11.txt | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/day11.lisp | | | 76 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | t/day11.lisp | | | 35 | +++++++++++++++++++++++++++++++++++ |
3 files changed, 166 insertions(+), 0 deletions(-)
diff --git a/input/day11.txt b/input/day11.txt
@@ -0,0 +1,55 @@
+Monkey 0:
+ Starting items: 97, 81, 57, 57, 91, 61
+ Operation: new = old * 7
+ Test: divisible by 11
+ If true: throw to monkey 5
+ If false: throw to monkey 6
+
+Monkey 1:
+ Starting items: 88, 62, 68, 90
+ Operation: new = old * 17
+ Test: divisible by 19
+ If true: throw to monkey 4
+ If false: throw to monkey 2
+
+Monkey 2:
+ Starting items: 74, 87
+ Operation: new = old + 2
+ Test: divisible by 5
+ If true: throw to monkey 7
+ If false: throw to monkey 4
+
+Monkey 3:
+ Starting items: 53, 81, 60, 87, 90, 99, 75
+ Operation: new = old + 1
+ Test: divisible by 2
+ If true: throw to monkey 2
+ If false: throw to monkey 1
+
+Monkey 4:
+ Starting items: 57
+ Operation: new = old + 6
+ Test: divisible by 13
+ If true: throw to monkey 7
+ If false: throw to monkey 0
+
+Monkey 5:
+ Starting items: 54, 84, 91, 55, 59, 72, 75, 70
+ Operation: new = old * old
+ Test: divisible by 7
+ If true: throw to monkey 6
+ If false: throw to monkey 3
+
+Monkey 6:
+ Starting items: 95, 79, 79, 68, 78
+ Operation: new = old + 3
+ Test: divisible by 3
+ If true: throw to monkey 1
+ If false: throw to monkey 3
+
+Monkey 7:
+ Starting items: 61, 97, 67
+ Operation: new = old + 4
+ Test: divisible by 17
+ If true: throw to monkey 0
+ If false: throw to monkey 5
diff --git a/src/day11.lisp b/src/day11.lisp
@@ -0,0 +1,76 @@
+(defpackage #:adventofcode2022/day11
+ (:use #:cl #:adventofcode2022))
+(in-package #:adventofcode2022/day11)
+
+(defclass monkey ()
+ ((items :initform nil
+ :accessor items)
+ (operation-fun :accessor operation-fun)
+ (test-fun :accessor test-fun)
+ (inspection-count :initform 0
+ :accessor inspection-count)))
+
+(defun parse-monkeys (inputs)
+ (loop with monkeys = nil
+ with current-monkey = nil
+ with test-divisible-by = nil
+ with test-if-true = nil
+ for input in inputs
+ do (cond
+ ((str:starts-with-p "Monkey " input)
+ (setf current-monkey (make-instance 'monkey))
+ (push current-monkey monkeys))
+ ((str:starts-with-p " Starting items:" input)
+ (setf (items current-monkey)
+ (mapcar (lambda (x) (parse-integer x))
+ (str:split ", " (subseq input 18)))))
+ ((str:starts-with-p " Operation:" input)
+ (setf (operation-fun current-monkey)
+ (eval (read-from-string
+ (format nil "(lambda (old) (~A old))" (subseq input 23))))))
+ ((str:starts-with-p " Test: divisible by" input)
+ (setf test-divisible-by (subseq input 21)))
+ ((str:starts-with-p " If true: throw to monkey" input)
+ (setf test-if-true (subseq input 29)))
+ ((str:starts-with-p " If false: throw to monkey" input)
+ (setf (test-fun current-monkey)
+ (eval (read-from-string
+ (format nil
+ "(lambda (item) (if (= (mod item ~A) 0) ~A ~A))"
+ test-divisible-by
+ test-if-true
+ (subseq input 29)))))))
+ finally (return (coerce (reverse monkeys) 'vector))))
+
+(defun let-monkeys-play (monkeys rounds)
+ (loop repeat rounds
+ do (loop for monkey across monkeys
+ do (loop with operation-fun = (operation-fun monkey)
+ with test-fun = (test-fun monkey)
+ for item in (items monkey)
+ for new-item = (setf item
+ (floor (/ (funcall operation-fun item) 3)))
+ for next-monkey-index = (funcall test-fun new-item)
+ for next-monkey = (aref monkeys next-monkey-index)
+ do (incf (inspection-count monkey))
+ do (setf (items next-monkey)
+ (append (items next-monkey) (list new-item))))
+ do (setf (items monkey) nil))))
+
+(defun task1 (inputs)
+ (let ((monkeys (parse-monkeys inputs)))
+ (let-monkeys-play monkeys 20)
+ (apply #'*
+ (map 'list
+ (lambda (monkey)
+ (inspection-count monkey))
+ (subseq (sort monkeys
+ (lambda (monkey-1 monkey-2)
+ (> (inspection-count monkey-1)
+ (inspection-count monkey-2))))
+ 0 2)))))
+
+(define-day 11
+ ()
+ #'task1
+ nil)
diff --git a/t/day11.lisp b/t/day11.lisp
@@ -0,0 +1,35 @@
+(in-package #:adventofcode2022/test)
+
+(defconstant +testdata-day11+ "Monkey 0:
+ Starting items: 79, 98
+ Operation: new = old * 19
+ Test: divisible by 23
+ If true: throw to monkey 2
+ If false: throw to monkey 3
+
+Monkey 1:
+ Starting items: 54, 65, 75, 74
+ Operation: new = old + 6
+ Test: divisible by 19
+ If true: throw to monkey 2
+ If false: throw to monkey 0
+
+Monkey 2:
+ Starting items: 79, 60, 97
+ Operation: new = old * old
+ Test: divisible by 13
+ If true: throw to monkey 1
+ If false: throw to monkey 3
+
+Monkey 3:
+ Starting items: 74
+ Operation: new = old + 3
+ Test: divisible by 17
+ If true: throw to monkey 0
+ If false: throw to monkey 1")
+
+(def-test day11-task1 ()
+ (is-true
+ (= 10605
+ (run-task 11 1
+ (make-string-input-stream +testdata-day11+)))))