From 6f3444e68b6ed2b4311c2a3e646ad95f32a3d028 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 11 Dec 2022 14:29:47 -0500 Subject: [PATCH] do day 11 --- 2022/input/day_11.txt | 55 ++++++++++ 2022/input/day_11_sample.txt | 27 +++++ 2022/src/day_11.rs | 192 +++++++++++++++++++++++++++++++++++ 2022/src/lib.rs | 1 + 4 files changed, 275 insertions(+) create mode 100644 2022/input/day_11.txt create mode 100644 2022/input/day_11_sample.txt create mode 100644 2022/src/day_11.rs diff --git a/2022/input/day_11.txt b/2022/input/day_11.txt new file mode 100644 index 0000000..5c9dd85 --- /dev/null +++ b/2022/input/day_11.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 66, 59, 64, 51 + Operation: new = old * 3 + Test: divisible by 2 + If true: throw to monkey 1 + If false: throw to monkey 4 + +Monkey 1: + Starting items: 67, 61 + Operation: new = old * 19 + Test: divisible by 7 + If true: throw to monkey 3 + If false: throw to monkey 5 + +Monkey 2: + Starting items: 86, 93, 80, 70, 71, 81, 56 + Operation: new = old + 2 + Test: divisible by 11 + If true: throw to monkey 4 + If false: throw to monkey 0 + +Monkey 3: + Starting items: 94 + Operation: new = old * old + Test: divisible by 19 + If true: throw to monkey 7 + If false: throw to monkey 6 + +Monkey 4: + Starting items: 71, 92, 64 + Operation: new = old + 8 + Test: divisible by 3 + If true: throw to monkey 5 + If false: throw to monkey 1 + +Monkey 5: + Starting items: 58, 81, 92, 75, 56 + Operation: new = old + 6 + Test: divisible by 5 + If true: throw to monkey 3 + If false: throw to monkey 6 + +Monkey 6: + Starting items: 82, 98, 77, 94, 86, 81 + Operation: new = old + 7 + Test: divisible by 17 + If true: throw to monkey 7 + If false: throw to monkey 2 + +Monkey 7: + Starting items: 54, 95, 70, 93, 88, 93, 63, 50 + Operation: new = old + 4 + Test: divisible by 13 + If true: throw to monkey 2 + If false: throw to monkey 0 diff --git a/2022/input/day_11_sample.txt b/2022/input/day_11_sample.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/2022/input/day_11_sample.txt @@ -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 diff --git a/2022/src/day_11.rs b/2022/src/day_11.rs new file mode 100644 index 0000000..54a2641 --- /dev/null +++ b/2022/src/day_11.rs @@ -0,0 +1,192 @@ +#[derive(Debug, Clone, Copy)] +enum Param { + Old, + Value(u64), +} + +#[derive(Debug, Clone, Copy)] +enum Op { + Add, + Mulitply, +} + +#[derive(Debug, Clone, Copy)] +struct Operation { + left: Param, + op: Op, + right: Param, +} + +#[derive(Debug, Clone)] +struct Monkey { + id: usize, + items: Vec, + operation: Operation, + test: u64, + test_failed_go_to: usize, + test_passed_go_to: usize, +} + +type Data = Vec; +type Output = u64; +fn parse(input: &str) -> Data { + input + .split("\n\n") + .map(|lines| { + let mut line_iter = lines.lines(); + + let id = { + let title_line = line_iter.next().unwrap(); + let (_prefix, id_block) = title_line.split_once(' ').unwrap(); + let (id, _rest) = id_block.split_once(':').unwrap(); + id.parse().unwrap() + }; + + let items = { + let items_line = line_iter.next().unwrap(); + let (_prefix, items) = items_line.split_once(": ").unwrap(); + items.split(", ").map(|num| num.parse().unwrap()).collect() + }; + + let operation = { + let operation_line = line_iter.next().unwrap(); + let (_prefix, rest) = operation_line.split_once("= ").unwrap(); + let (left_str, rest) = rest.split_once(' ').unwrap(); + let left = match left_str { + "old" => Param::Old, + s => Param::Value(s.parse().unwrap()), + }; + + let (op_str, right_str) = rest.split_once(' ').unwrap(); + let op_char = op_str.chars().next().unwrap(); + let op = match op_char { + '+' => Op::Add, + '*' => Op::Mulitply, + _ => panic!("expected + or *; got {}", op_str), + }; + + let right = match right_str { + "old" => Param::Old, + s => Param::Value(s.parse().unwrap()), + }; + Operation { left, op, right } + }; + + let test = { + let test_line = line_iter.next().unwrap(); + let (_prefix, num) = test_line.split_once("by ").unwrap(); + num.parse().unwrap() + }; + + let test_passed_go_to = { + let passed_line = line_iter.next().unwrap(); + let (_prefix, num) = passed_line.split_once("monkey ").unwrap(); + num.parse().unwrap() + }; + + let test_failed_go_to = { + let failed_line = line_iter.next().unwrap(); + let (_prefix, num) = failed_line.split_once("monkey ").unwrap(); + num.parse().unwrap() + }; + + Monkey { + id, + items, + operation, + test, + test_failed_go_to, + test_passed_go_to, + } + }) + .collect() +} +fn part_one(mut data: Data) -> Output { + let mut counts = vec![0; data.len()]; + + for _ in 1..=20 { + for i in 0..data.len() { + for j in 0..data[i].items.len() { + let left = match data[i].operation.left { + Param::Value(v) => v, + Param::Old => data[i].items[j], + }; + let right = match data[i].operation.right { + Param::Value(v) => v, + Param::Old => data[i].items[j], + }; + let new_value = match data[i].operation.op { + Op::Add => left + right, + Op::Mulitply => left * right, + } / 3; + if new_value % data[i].test == 0 { + let idx = data[i].test_passed_go_to; + data[idx].items.push(new_value); + } else { + let idx = data[i].test_failed_go_to; + data[idx].items.push(new_value); + } + } + counts[i] += data[i].items.len(); + data[i].items.clear(); + } + } + + counts.sort(); + counts.reverse(); + + counts[0] as u64 * counts[1] as u64 +} +fn part_two(mut data: Data) -> Output { + let mut counts = vec![0; data.len()]; + + let test_gcd = data.iter().fold(1, |acc, curr| acc * curr.test); + + for round in 1..=10000 { + for i in 0..data.len() { + for j in 0..data[i].items.len() { + let left = match data[i].operation.left { + Param::Value(v) => v, + Param::Old => data[i].items[j], + }; + let right = match data[i].operation.right { + Param::Value(v) => v, + Param::Old => data[i].items[j], + }; + let new_value = match data[i].operation.op { + Op::Add => left + right, + Op::Mulitply => left * right, + }; + if new_value % data[i].test == 0 { + let idx = data[i].test_passed_go_to; + data[idx].items.push(new_value % test_gcd); + } else { + let idx = data[i].test_failed_go_to; + data[idx].items.push(new_value % test_gcd); + } + } + counts[i] += data[i].items.len(); + data[i].items.clear(); + } + match round { + 1 | 20 | 1000 => { + dbg!(&counts, round); + } + _ => {} + } + } + + counts.sort(); + counts.reverse(); + + counts[0] as u64 * counts[1] as u64 +} + +advent_of_code_macro::generate_tests!( + day 11, + parse, + part_one, + part_two, + sample tests [10_605, 2_713_310_158], + star tests [90_294, 18_170_818_354] +); diff --git a/2022/src/lib.rs b/2022/src/lib.rs index cc23b91..62054ab 100644 --- a/2022/src/lib.rs +++ b/2022/src/lib.rs @@ -9,3 +9,4 @@ mod day_07; mod day_08; mod day_09; mod day_10; +mod day_11;