From 52a8c9298ee88925f936ddc86664f2711f65c330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Tue, 13 Dec 2022 00:11:48 +0000 Subject: [PATCH] day 11 --- input/2022/day11.txt | 55 ++++++++++++ src/day11.rs | 201 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 257 insertions(+) create mode 100644 input/2022/day11.txt create mode 100644 src/day11.rs diff --git a/input/2022/day11.txt b/input/2022/day11.txt new file mode 100644 index 0000000..619c5cb --- /dev/null +++ b/input/2022/day11.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 75, 75, 98, 97, 79, 97, 64 + Operation: new = old * 13 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 7 + +Monkey 1: + Starting items: 50, 99, 80, 84, 65, 95 + Operation: new = old + 2 + Test: divisible by 3 + If true: throw to monkey 4 + If false: throw to monkey 5 + +Monkey 2: + Starting items: 96, 74, 68, 96, 56, 71, 75, 53 + Operation: new = old + 1 + Test: divisible by 11 + If true: throw to monkey 7 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 83, 96, 86, 58, 92 + Operation: new = old + 8 + Test: divisible by 17 + If true: throw to monkey 6 + If false: throw to monkey 1 + +Monkey 4: + Starting items: 99 + Operation: new = old * old + Test: divisible by 5 + If true: throw to monkey 0 + If false: throw to monkey 5 + +Monkey 5: + Starting items: 60, 54, 83 + Operation: new = old + 4 + Test: divisible by 2 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 6: + Starting items: 77, 67 + Operation: new = old * 17 + Test: divisible by 13 + If true: throw to monkey 4 + If false: throw to monkey 1 + +Monkey 7: + Starting items: 95, 65, 58, 76 + Operation: new = old + 5 + Test: divisible by 7 + If true: throw to monkey 3 + If false: throw to monkey 6 diff --git a/src/day11.rs b/src/day11.rs new file mode 100644 index 0000000..cbaec97 --- /dev/null +++ b/src/day11.rs @@ -0,0 +1,201 @@ +#[derive(Clone)] +struct Operation { + str: String, +} + +impl Operation { + fn apply(&self, item: u64) -> u64 { + let parts: Vec<&str> = self.str.split(" ").collect(); + + let mut right: u64 = item; + if parts[2] != "old" { + right = parts[2].parse::().unwrap(); + } + + match parts[1] { + "*" => item.wrapping_mul(right), + "+" => item.wrapping_add(right), + _ => panic!("operator not implemented"), + } + } +} + +#[derive(Clone)] +struct Test { + divisible: u64, + target_positive: usize, + target_negative: usize, +} + +impl Test { + fn result(&self, item: u64) -> usize { + if item % self.divisible == 0 { + self.target_positive + } else { + self.target_negative + } + } +} + +#[derive(Clone)] +struct Monkey { + items: Vec, + operation: Operation, + test: Test, + inspections: usize, +} + +impl Monkey { + fn turn(&mut self, transform: impl Fn(u64) -> u64) -> Vec<(usize, u64)> { + let mut give: Vec<(usize, u64)> = Vec::new(); + + loop { + if self.items.len() == 0 { + break; + } + + self.inspections += 1; + let mut c = self.operation.apply(self.items.pop().unwrap()); + c = transform(c); + + let target = self.test.result(c); + + give.push((target, c)); + + if self.items.len() == 0 { + break; + } + } + + give + } +} + +type Input = Vec; + +#[aoc_generator(day11)] +fn parse_input(input: &str) -> Input { + input + .split("\n\n") + .map(|m| { + let lines: Vec<&str> = m.lines().skip(1).collect(); + + let (_, numbers_str) = lines[0].split_once(": ").unwrap(); + let items: Vec = numbers_str + .split(", ") + .map(|str| str.parse::().unwrap()) + .collect(); + + let operation = Operation { + str: lines[1].split(" = ").collect::>()[1].into(), + }; + + let d = lines[2].split(" by ").collect::>()[1] + .parse::() + .unwrap(); + + let positive = lines[3].split("monkey ").collect::>()[1] + .parse::() + .unwrap(); + + let negative = lines[4].split("monkey ").collect::>()[1] + .parse::() + .unwrap(); + + Monkey { + items, + operation, + test: Test { + divisible: d, + target_positive: positive, + target_negative: negative, + }, + inspections: 0, + } + }) + .collect::>() +} + +#[aoc(day11, part1)] +fn part1(input: &Input) -> usize { + let mut input = input.clone(); + + for _ in 0..20 { + for i in 0..input.len() { + let give = input[i].turn(|w| w / 3); + + give.iter() + .rev() + .for_each(|(target, item)| input[*target].items.push(*item)); + } + } + + let mut inspections = input.iter().map(|m| m.inspections).collect::>(); + inspections.sort(); + + inspections.iter().rev().take(2).product() +} + +#[aoc(day11, part2)] +fn part2(input: &Input) -> usize { + let mut input = input.clone(); + let modulus = input.iter().map(|m| m.test.divisible).product::(); + + for _ in 0..10000 { + for i in 0..input.len() { + let give = input[i].turn(|w| w % modulus); + + give.iter() + .rev() + .for_each(|(target, item)| input[*target].items.push(*item)); + } + } + + let mut inspections = input.iter().map(|m| m.inspections).collect::>(); + inspections.sort(); + + inspections.iter().rev().take(2).product() +} + +#[cfg(test)] +mod tests { + use super::*; + + const INPUT: &str = r##"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"##; + + #[test] + fn test_part1() { + assert_eq!(10605, part1(&parse_input(INPUT))); + } + + #[test] + fn test_part2() { + assert_eq!(2713310158, part2(&parse_input(INPUT))); + } +} diff --git a/src/lib.rs b/src/lib.rs index 200e55c..a864630 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ extern crate core; pub mod day1; pub mod day10; +pub mod day11; pub mod day2; pub mod day3; pub mod day4;