From 6ddb4c4c8f64ccb49c1f91efff1a2da96a6fb0fb Mon Sep 17 00:00:00 2001 From: Lars Martens Date: Sun, 11 Dec 2022 11:55:54 +0100 Subject: [PATCH] Solve day 11 --- input/11 | 55 +++++++++++++++++++ input/11-test | 27 ++++++++++ src/bin/11.rs | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 input/11 create mode 100644 input/11-test create mode 100644 src/bin/11.rs diff --git a/input/11 b/input/11 new file mode 100644 index 0000000..76ed4aa --- /dev/null +++ b/input/11 @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 75, 63 + Operation: new = old * 3 + Test: divisible by 11 + If true: throw to monkey 7 + If false: throw to monkey 2 + +Monkey 1: + Starting items: 65, 79, 98, 77, 56, 54, 83, 94 + Operation: new = old + 3 + Test: divisible by 2 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 66 + Operation: new = old + 5 + Test: divisible by 5 + If true: throw to monkey 7 + If false: throw to monkey 5 + +Monkey 3: + Starting items: 51, 89, 90 + Operation: new = old * 19 + Test: divisible by 7 + If true: throw to monkey 6 + If false: throw to monkey 4 + +Monkey 4: + Starting items: 75, 94, 66, 90, 77, 82, 61 + Operation: new = old + 1 + Test: divisible by 17 + If true: throw to monkey 6 + If false: throw to monkey 1 + +Monkey 5: + Starting items: 53, 76, 59, 92, 95 + Operation: new = old + 2 + Test: divisible by 19 + If true: throw to monkey 4 + If false: throw to monkey 3 + +Monkey 6: + Starting items: 81, 61, 75, 89, 70, 92 + Operation: new = old * old + Test: divisible by 3 + If true: throw to monkey 0 + If false: throw to monkey 1 + +Monkey 7: + Starting items: 81, 86, 62, 87 + Operation: new = old + 8 + Test: divisible by 13 + If true: throw to monkey 3 + If false: throw to monkey 5 diff --git a/input/11-test b/input/11-test new file mode 100644 index 0000000..c04eddb --- /dev/null +++ b/input/11-test @@ -0,0 +1,27 @@ +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 \ No newline at end of file diff --git a/src/bin/11.rs b/src/bin/11.rs new file mode 100644 index 0000000..fdece9f --- /dev/null +++ b/src/bin/11.rs @@ -0,0 +1,146 @@ +use std::{collections::VecDeque, fmt, str::FromStr}; + +use aoc2022::*; +use itertools::Itertools; + +const INPUT: &str = include_str!("../../input/11"); + +fn main() { + let mut troop = Troop::from_input(); + troop.play(20, 3); + solved_level_1(troop.level()); + + let mut troop = Troop::from_input(); + troop.play(10000, 1); + solved_level_2(troop.level()); +} + +#[derive(Debug)] +struct Troop(Vec); + +impl Troop { + fn level(&self) -> usize { + let mut inspections = self.0.iter().map(|m| m.inspected).collect_vec(); + inspections.sort(); + inspections.reverse(); + inspections[0] * inspections[1] + } + + fn play(&mut self, rounds: usize, divider: u64) { + for _ in 0..rounds { + for monkey in 0..self.0.len() { + self.monkey_play(monkey, divider); + } + } + } + + fn monkey_play(&mut self, monkey: usize, divider: u64) { + self.0[monkey].inspected += self.0[monkey].items.len(); + + let modulus: u64 = self.0.iter().map(|m| m.test).product(); + + while let Some(mut item) = self.0[monkey].items.pop_front() { + let target = { + let monkey = &self.0[monkey]; + match monkey.op { + Operation::Add(n) => item += n, + Operation::Mul(n) => item *= n, + Operation::Square => item *= item, + }; + item /= divider; + + item %= modulus; + + if item % monkey.test == 0 { + monkey.throw_true + } else { + monkey.throw_false + } + }; + + self.0[target].items.push_back(item); + } + } + + fn from_input() -> Self { + let mut monkeys = Vec::new(); + // Placeholder while building. + let mut current = Monkey { + items: VecDeque::new(), + op: Operation::Add(0u8.into()), + test: 0, + throw_true: 0, + throw_false: 0, + inspected: 0, + }; + + for (i, line) in INPUT.lines().enumerate() { + match i % 7 { + 0 | 6 => { /* Monkey index or empty line can be ignored */ } + 1 => { + let (_, items) = line.split_once(": ").unwrap(); + current.items = items + .split(", ") + .map(|item| item.parse().unwrap()) + .collect(); + } + 2 => { + current.op = if line.contains("old * old") { + Operation::Square + } else if line.contains('*') { + Operation::Mul(line.parse_last()) + } else { + Operation::Add(line.parse_last()) + } + } + 3 => current.test = line.parse_last(), + 4 => current.throw_true = line.parse_last(), + 5 => { + current.throw_false = line.parse_last(); + // This is the final line + monkeys.push(current.clone()); + } + i => unreachable!("{i} is impossible to get in mod 7"), + } + } + + Self(monkeys) + } +} + +#[derive(Debug, Clone)] +struct Monkey { + items: VecDeque, + op: Operation, + test: u64, + throw_true: usize, + throw_false: usize, + inspected: usize, +} + +#[derive(Debug, Clone)] +enum Operation { + Add(u64), + Mul(u64), + Square, +} + +/// Helper trait to make code more readable. +/// Parses the last element from a whitespace separated str. +trait ParseLast { + fn parse_last(self) -> T; +} + +impl<'a, T> ParseLast for &'a str +where + T: FromStr, + T::Err: fmt::Debug, +{ + fn parse_last(self) -> T { + self.split_ascii_whitespace() + .last() + .unwrap() + .parse() + .unwrap() + } +}