aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2022/11
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2022/11')
-rw-r--r--AoC2022/11/eg-in28
-rw-r--r--AoC2022/11/input55
-rw-r--r--AoC2022/11/solver.el100
3 files changed, 183 insertions, 0 deletions
diff --git a/AoC2022/11/eg-in b/AoC2022/11/eg-in
new file mode 100644
index 0000000..dc98f0b
--- /dev/null
+++ b/AoC2022/11/eg-in
@@ -0,0 +1,28 @@
+
+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
diff --git a/AoC2022/11/input b/AoC2022/11/input
new file mode 100644
index 0000000..809f96c
--- /dev/null
+++ b/AoC2022/11/input
@@ -0,0 +1,55 @@
+Monkey 0:
+ Starting items: 57, 58
+ Operation: new = old * 19
+ Test: divisible by 7
+ If true: throw to monkey 2
+ If false: throw to monkey 3
+
+Monkey 1:
+ Starting items: 66, 52, 59, 79, 94, 73
+ Operation: new = old + 1
+ Test: divisible by 19
+ If true: throw to monkey 4
+ If false: throw to monkey 6
+
+Monkey 2:
+ Starting items: 80
+ Operation: new = old + 6
+ Test: divisible by 5
+ If true: throw to monkey 7
+ If false: throw to monkey 5
+
+Monkey 3:
+ Starting items: 82, 81, 68, 66, 71, 83, 75, 97
+ Operation: new = old + 5
+ Test: divisible by 11
+ If true: throw to monkey 5
+ If false: throw to monkey 2
+
+Monkey 4:
+ Starting items: 55, 52, 67, 70, 69, 94, 90
+ Operation: new = old * old
+ Test: divisible by 17
+ If true: throw to monkey 0
+ If false: throw to monkey 3
+
+Monkey 5:
+ Starting items: 69, 85, 89, 91
+ Operation: new = old + 7
+ Test: divisible by 13
+ If true: throw to monkey 1
+ If false: throw to monkey 7
+
+Monkey 6:
+ Starting items: 75, 53, 73, 52, 75
+ Operation: new = old * 7
+ Test: divisible by 2
+ If true: throw to monkey 0
+ If false: throw to monkey 4
+
+Monkey 7:
+ Starting items: 94, 60, 79
+ Operation: new = old + 2
+ Test: divisible by 3
+ If true: throw to monkey 1
+ If false: throw to monkey 6
diff --git a/AoC2022/11/solver.el b/AoC2022/11/solver.el
new file mode 100644
index 0000000..397b911
--- /dev/null
+++ b/AoC2022/11/solver.el
@@ -0,0 +1,100 @@
+;;; solver.el --- Day 11 -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2022 Óscar Nájera
+;;
+;; Author: Óscar Nájera <hi@oscarnajera.com>
+;; Maintainer: Óscar Nájera <hi@oscarnajera.com>
+;; Created: December 11, 2022
+;; Modified: December 11, 2022
+;;
+;; This file is not part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;; Day 11
+;;
+;;; Code:
+
+(require 'subr-x)
+(require 'cl-lib)
+
+(cl-defstruct (monkey (:constructor monkey--create)
+ (:copier nil))
+ "Monkey container"
+ id
+ items
+ worry-level
+ throw-to)
+
+(defun solver-monkey-make (id items operation divisor true-target false-target)
+ (let ((op (if (string-prefix-p "*" operation) #'* #'+))
+ (operand (unless (string-suffix-p "old" operation)
+ (string-to-number (substring operation 1))))
+ (div (string-to-number divisor))
+ (true (string-to-number true-target))
+ (false (string-to-number false-target)))
+ (monkey--create
+ :id (string-to-number id)
+ :items (nreverse (mapcar #'string-to-number (split-string items ", ")))
+ :worry-level (lambda (item)
+ (thread-first
+ (funcall op item (or operand item)) ;; value item
+ (floor 3))) ;; loose interest
+
+ :throw-to (lambda (item)
+ (thread-first item
+ (mod div) ;; throw input
+ (= 0) ;; divisble
+ (if true false))))))
+
+(defun solver-parse-monkey-entry ()
+ (when
+ (re-search-forward (rx bol "Monkey " (group digit) ":" (+ space)
+ "Starting items: " (group (+ (1+ digit) (? ", "))) (+ space)
+ "Operation: new = old " (group (1+ any)) (+ space)
+ "Test: divisible by " (group (1+ digit)) (+ space)
+ "If true: throw to monkey " (group digit) (+ space)
+ "If false: throw to monkey " (group digit) eol)
+ nil t)
+ (apply #'solver-monkey-make
+ (mapcar #'match-string (number-sequence 1 6)))))
+
+(defun solver-monkey-business (works)
+ (let ((ranks (sort works #'>)))
+ (* (aref ranks 0) (aref ranks 1))))
+
+(defun solver-get-monkeys (filename)
+ (with-temp-buffer
+ (insert-file-contents filename)
+ (goto-char (point-min))
+ (cl-loop for monkey = (solver-parse-monkey-entry) while monkey collect monkey)))
+
+(defun solver-monkey-rounds (monkeys rounds)
+ (let ((monkey-work (make-vector (length monkeys) 0)))
+ ;; play round
+ (dotimes (_ rounds)
+ (dolist (monkey monkeys)
+ (let ((items (nreverse (monkey-items monkey))))
+ (setf (monkey-items monkey) nil)
+ (cl-incf (aref monkey-work (monkey-id monkey)) (length items))
+ (mapc (lambda (item)
+ (let* ((item-concern (funcall (monkey-worry-level monkey) item))
+ (target-monkey (funcall (monkey-throw-to monkey) item-concern)))
+ (push item-concern (monkey-items (cl-find target-monkey monkeys :key #'monkey-id)))))
+ items))
+ ;; (message "monkey %d - items: %s\n all: %S" (monkey-id monkey) (monkey-items monkey)
+ ;; (mapcar #'monkey-items monkeys))
+ ))
+ (solver-monkey-business monkey-work)))
+
+(= 10605
+ (thread-first
+ "eg-in"
+ (solver-get-monkeys)
+ (solver-monkey-rounds 20)))
+
+(= 50830
+ (thread-first
+ "input"
+ (solver-get-monkeys)
+ (solver-monkey-rounds 20)))