diff --git a/2022/day11.txt b/2022/day11.txt new file mode 100644 index 0000000..02339f0 --- /dev/null +++ b/2022/day11.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 64 + Operation: new = old * 7 + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 60, 84, 84, 65 + Operation: new = old + 7 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 7 + +Monkey 2: + Starting items: 52, 67, 74, 88, 51, 61 + Operation: new = old * 3 + Test: divisible by 5 + If true: throw to monkey 5 + If false: throw to monkey 7 + +Monkey 3: + Starting items: 67, 72 + Operation: new = old + 3 + Test: divisible by 2 + If true: throw to monkey 1 + If false: throw to monkey 2 + +Monkey 4: + Starting items: 80, 79, 58, 77, 68, 74, 98, 64 + Operation: new = old * old + Test: divisible by 17 + If true: throw to monkey 6 + If false: throw to monkey 0 + +Monkey 5: + Starting items: 62, 53, 61, 89, 86 + Operation: new = old + 8 + Test: divisible by 11 + If true: throw to monkey 4 + If false: throw to monkey 6 + +Monkey 6: + Starting items: 86, 89, 82 + Operation: new = old + 2 + Test: divisible by 7 + If true: throw to monkey 3 + If false: throw to monkey 0 + +Monkey 7: + Starting items: 92, 81, 70, 96, 69, 84, 83 + Operation: new = old + 4 + Test: divisible by 3 + If true: throw to monkey 4 + If false: throw to monkey 5 \ No newline at end of file diff --git a/2022/src/days/day11.rs b/2022/src/days/day11.rs new file mode 100644 index 0000000..68dcd2e --- /dev/null +++ b/2022/src/days/day11.rs @@ -0,0 +1,168 @@ +use anyhow::{anyhow, Result}; +use std::collections::{BinaryHeap, VecDeque}; +use std::fs; + +#[derive(Default, Debug)] +enum Ops { + Plus(u64), + Mult(u64), + #[default] + Square, +} + +#[derive(Default, Debug)] +struct Monkey { + items: VecDeque, + op: Ops, + test: u64, + result: [usize; 2], +} + +pub fn run() -> Result<()> { + #[cfg(not(feature = "test_input"))] + let file_contents = fs::read_to_string("day11.txt")?; + + #[cfg(feature = "test_input")] + let file_contents = fs::read_to_string("tests/day11.txt")?; + + let mut monkeys: Vec = Vec::with_capacity(8); + let mut lines = file_contents.lines(); + + while let Some(line) = lines.next() { + if line.is_empty() { + continue; + } + if line.starts_with("Monkey") { + let mut m = Monkey::default(); + for i in lines.next().unwrap().split_whitespace().skip(2) { + if let Some(s) = i.strip_suffix(",") { + m.items.push_back(s.parse::().unwrap()); + } else { + m.items.push_back(i.parse::().unwrap()); + } + } + let mut ops = lines.next().unwrap().split_whitespace().skip(4); + let op_symbol = ops.next().unwrap(); + let op_val = ops.next().unwrap(); + match op_symbol { + "*" => { + m.op = if op_val == "old" { + Ops::Square + } else { + let val: u64 = op_val.parse().unwrap(); + Ops::Mult(val) + } + } + "+" => { + let val: u64 = op_val.parse().unwrap(); + m.op = Ops::Plus(val); + } + _ => return Err(anyhow!("invalid op code")), + } + let t = lines + .next() + .unwrap() + .split_whitespace() + .skip(3) + .next() + .unwrap() + .parse::() + .unwrap(); + m.test = t; + let tmonkey: usize = lines + .next() + .unwrap() + .split_whitespace() + .skip(5) + .next() + .unwrap() + .parse() + .unwrap(); + let fmonkey: usize = lines + .next() + .unwrap() + .split_whitespace() + .skip(5) + .next() + .unwrap() + .parse() + .unwrap(); + m.result = [tmonkey, fmonkey]; + monkeys.push(m); + } + } + + part_one_items(&mut monkeys); + part_two_items(&mut monkeys); + + Ok(()) +} + +fn match_op(op: &Ops, old: u64) -> u64 { + match op { + Ops::Plus(t) => old + t, + Ops::Mult(t) => old * t, + Ops::Square => old * old, + } +} + +fn part_one_items(monkeys: &mut Vec) { + let mut inspections: Vec = Vec::with_capacity(8); + let mut items: Vec> = monkeys.iter().map(|m| m.items.clone()).collect(); + + for _ in 1..=20 { + for m in 0..monkeys.len() { + if let None = inspections.get(m) { + inspections.push(0); + } + while let Some(item) = items[m].pop_front() { + inspections[m] += 1; + let score = (match_op(&monkeys[m].op, item) as f32 / 3.0).floor() as u64; + if score % monkeys[m].test == 0 { + items[monkeys[m].result[0]].push_back(score); + } else { + items[monkeys[m].result[1]].push_back(score); + } + } + } + } + + let mut bh: BinaryHeap = BinaryHeap::from(inspections); + let one = bh.pop().unwrap(); + let two = bh.pop().unwrap(); + println!("part one {}*{}={}", one, two, one * two); +} + +fn part_two_items(monkeys: &mut Vec) { + let mut inspections: Vec = Vec::with_capacity(8); + let mut items: Vec> = monkeys.iter().map(|m| m.items.clone()).collect(); + + #[cfg(feature = "test_input")] + let cd = 96577; + + // grep Test day11.txt | awk 'BEGIN { S=1} { S=S*$4} END {print S}' + #[cfg(not(feature = "test_input"))] + let cd = 9699690; + + for _ in 1..=10000 { + for m in 0..monkeys.len() { + if let None = inspections.get(m) { + inspections.push(0); + } + while let Some(item) = items[m].pop_front() { + inspections[m] += 1; + let score = match_op(&monkeys[m].op, item); + if score % monkeys[m].test == 0 { + items[monkeys[m].result[0]].push_back(score % cd); + } else { + items[monkeys[m].result[1]].push_back(score % cd); + } + } + } + } + + let mut bh: BinaryHeap = BinaryHeap::from(inspections); + let one = bh.pop().unwrap(); + let two = bh.pop().unwrap(); + println!("part two {}*{}={}", one, two, one * two); +} diff --git a/2022/src/days/mod.rs b/2022/src/days/mod.rs index bcca163..737f5f6 100644 --- a/2022/src/days/mod.rs +++ b/2022/src/days/mod.rs @@ -1,5 +1,6 @@ pub mod day1; pub mod day10; +pub mod day11; pub mod day2; pub mod day3; pub mod day4; diff --git a/2022/src/main.rs b/2022/src/main.rs index 4a7efbb..7af5b0a 100644 --- a/2022/src/main.rs +++ b/2022/src/main.rs @@ -42,6 +42,9 @@ fn run_day(number: i32) -> Result<()> { 10 => { days::day10::run()?; } + 11 => { + days::day11::run()?; + } _ => return Err(anyhow!("Invalid day provided")), } Ok(()) diff --git a/2022/tests/day11.txt b/2022/tests/day11.txt new file mode 100644 index 0000000..30e09e5 --- /dev/null +++ b/2022/tests/day11.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