blob: 397b911b8fa9cc4748b4d395865b47b29badb0d3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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)))
|