summaryrefslogtreecommitdiff
path: root/2022/Rust/src/day11.rs
diff options
context:
space:
mode:
Diffstat (limited to '2022/Rust/src/day11.rs')
-rw-r--r--2022/Rust/src/day11.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/2022/Rust/src/day11.rs b/2022/Rust/src/day11.rs
new file mode 100644
index 0000000..d0c16de
--- /dev/null
+++ b/2022/Rust/src/day11.rs
@@ -0,0 +1,147 @@
+use std::{collections::VecDeque, str::FromStr, string::ParseError};
+
+#[derive(Debug, Clone, Copy)]
+enum Op {
+ Add(i64),
+ Prod(i64),
+ Square,
+}
+
+#[derive(Debug, Clone)]
+struct Monkey {
+ starting_items: VecDeque<i64>,
+ inspected_items: i64,
+ operation: Op,
+ test: i64,
+ monkey_true: i64,
+ monkey_false: i64,
+}
+
+fn parse_items(line: &str) -> String {
+ line.chars().skip_while(|&ch| ch != ':').skip(2).collect()
+}
+
+fn get_last_token(line: &str) -> i64 {
+ line.split(" ")
+ .last()
+ .unwrap()
+ .parse::<i64>()
+ .expect("Should be parasble to i64")
+}
+
+impl FromStr for Monkey {
+ type Err = ParseError;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let lines: Vec<_> = s.lines().collect();
+ let items: VecDeque<i64> = parse_items(lines[1])
+ .split(", ")
+ .map(|x| x.parse::<i64>().expect("Should be parsable to i64"))
+ .collect();
+ let line_2: Vec<_> = lines[2].split(" ").collect();
+ let v: Vec<_> = line_2.iter().rev().take(2).collect();
+ let op = {
+ match *v[0] {
+ "old" => Op::Square,
+ _ => match *v[1] {
+ "+" => Op::Add(v[0].parse::<i64>().unwrap()),
+ "*" => Op::Prod(v[0].parse::<i64>().unwrap()),
+ _ => unreachable!(),
+ },
+ }
+ };
+ let test = get_last_token(lines[3]);
+ let monkey_true = get_last_token(lines[4]);
+ let monkey_false = get_last_token(lines[5]);
+ Ok(Monkey {
+ starting_items: items,
+ inspected_items: 0,
+ operation: op,
+ test,
+ monkey_true,
+ monkey_false,
+ })
+ }
+}
+
+fn solve_part_one(data: &str) -> i64 {
+ let monkeys_input: Vec<_> = data.split("\n\n").collect();
+ let mut monkeys: Vec<_> = monkeys_input
+ .iter()
+ .map(|monkey| Monkey::from_str(monkey).unwrap())
+ .collect();
+
+ for _ in 0..20 {
+ for i in 0..monkeys.len() {
+ while !monkeys[i].starting_items.is_empty() {
+ use Op::*;
+ monkeys[i].inspected_items += 1;
+ let mut worry = monkeys[i].starting_items[0];
+ match monkeys[i].operation {
+ Add(x) => worry += x,
+ Prod(x) => worry *= x,
+ Square => worry *= worry,
+ };
+ worry /= 3;
+ let monkey_truth = monkeys[i].monkey_true as usize;
+ let monkey_false = monkeys[i].monkey_false as usize;
+ match worry % monkeys[i].test == 0 {
+ true => monkeys[monkey_truth].starting_items.push_back(worry),
+ false => monkeys[monkey_false].starting_items.push_back(worry),
+ }
+ monkeys[i].starting_items.pop_front();
+ }
+ }
+ }
+ let mut inspected_items: Vec<_> = monkeys.iter().map(|x| x.inspected_items).collect();
+ inspected_items.sort();
+ inspected_items.reverse();
+ inspected_items.iter().take(2).product()
+}
+
+fn solve_part_two(data: &str) -> i64 {
+ let monkeys_input: Vec<_> = data.split("\n\n").collect();
+ let mut monkeys: Vec<_> = monkeys_input
+ .iter()
+ .map(|monkey| Monkey::from_str(monkey).unwrap())
+ .collect();
+
+ for _ in 0..10000 {
+ for i in 0..monkeys.len() {
+ let divisors_product: i64 = monkeys.iter().map(|x| x.test).product();
+ while !monkeys[i].starting_items.is_empty() {
+ use Op::*;
+ monkeys[i].inspected_items += 1;
+ let mut worry = monkeys[i].starting_items[0];
+ worry %= divisors_product;
+ match monkeys[i].operation {
+ Add(x) => worry = worry + x,
+ Prod(x) => worry = worry * x,
+ Square => worry = worry * worry,
+ };
+ let monkey_truth = monkeys[i].monkey_true as usize;
+ let monkey_false = monkeys[i].monkey_false as usize;
+ match worry % monkeys[i].test == 0 {
+ true => monkeys[monkey_truth].starting_items.push_back(worry),
+ false => monkeys[monkey_false].starting_items.push_back(worry),
+ }
+ monkeys[i].starting_items.pop_front();
+ }
+ }
+ }
+ let mut inspected_items: Vec<_> = monkeys
+ .iter()
+ .map(|x| x.inspected_items)
+ .collect::<Vec<_>>();
+ inspected_items.sort();
+ inspected_items.reverse();
+ inspected_items.iter().take(2).product()
+}
+
+fn main() {
+ let test = include_str!("../input/day11.test");
+ let prod = include_str!("../input/day11.prod");
+ println!("part1: test {:?}", solve_part_one(test));
+ println!("part1: prod {:?}", solve_part_one(prod));
+ println!("part2: test {:?}", solve_part_two(test));
+ println!("part2: prod {:?}", solve_part_two(prod));
+}