Add 2022/11

This commit is contained in:
kageru 2022-12-11 21:32:32 +01:00
parent 3055794744
commit 1cfc30921f
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
2 changed files with 189 additions and 0 deletions

55
2022/inputs/day11 Normal file
View File

@ -0,0 +1,55 @@
Monkey 0:
Starting items: 96, 60, 68, 91, 83, 57, 85
Operation: new = old * 2
Test: divisible by 17
If true: throw to monkey 2
If false: throw to monkey 5
Monkey 1:
Starting items: 75, 78, 68, 81, 73, 99
Operation: new = old + 3
Test: divisible by 13
If true: throw to monkey 7
If false: throw to monkey 4
Monkey 2:
Starting items: 69, 86, 67, 55, 96, 69, 94, 85
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 6
If false: throw to monkey 5
Monkey 3:
Starting items: 88, 75, 74, 98, 80
Operation: new = old + 5
Test: divisible by 7
If true: throw to monkey 7
If false: throw to monkey 1
Monkey 4:
Starting items: 82
Operation: new = old + 8
Test: divisible by 11
If true: throw to monkey 0
If false: throw to monkey 2
Monkey 5:
Starting items: 72, 92, 92
Operation: new = old * 5
Test: divisible by 3
If true: throw to monkey 6
If false: throw to monkey 3
Monkey 6:
Starting items: 74, 61
Operation: new = old * old
Test: divisible by 2
If true: throw to monkey 3
If false: throw to monkey 1
Monkey 7:
Starting items: 76, 86, 83, 55
Operation: new = old + 4
Test: divisible by 5
If true: throw to monkey 4
If false: throw to monkey 0

134
2022/src/bin/day11.rs Normal file
View File

@ -0,0 +1,134 @@
#![feature(test)]
extern crate test;
use aoc2022::{boilerplate, common::*};
const DAY: usize = 11;
type Parsed = Vec<Monkey>;
#[derive(Clone, Debug)]
struct Monkey {
inspection_count: usize,
items: Vec<usize>,
op: MonkeyOp,
div_test: usize,
true_dst: usize,
false_dst: usize,
}
#[derive(Copy, Clone, Debug)]
enum MonkeyOp {
Add(Option<usize>, Option<usize>),
Mul(Option<usize>, Option<usize>),
}
fn parse_input(raw: &str) -> Parsed {
raw.split("\n\n")
.map(|raw_monkey| {
let mut lines = raw_monkey.lines();
let [_, start, op, test, if_true, if_false] = std::array::from_fn(|_| lines.next().unwrap());
let items = start[18..].split(", ").map(parse_num).collect();
let div_test = parse_num(&test[21..]);
let true_dst = parse_num(&if_true[29..]);
let false_dst = parse_num(&if_false[30..]);
let op = match op[19..].split(' ').collect::<Vec<_>>().as_slice() {
[x, "+", y] => MonkeyOp::Add(x.parse().ok(), y.parse().ok()),
[x, "*", y] => MonkeyOp::Mul(x.parse().ok(), y.parse().ok()),
_ => unreachable!(),
};
Monkey { inspection_count: 0, items, op, div_test, true_dst, false_dst }
})
.collect()
}
// Stolen from my 2019 day 12 solution
fn lcm(x: usize, y: usize) -> usize {
fn gcd(mut x: usize, mut y: usize) -> usize {
let mut remainder;
while y != 0 {
remainder = x % y;
x = y;
y = remainder;
}
x
}
x * y / gcd(x, y)
}
fn part1(parsed: &Parsed) -> usize {
monkey_business::<20, 3>(parsed)
}
fn part2(parsed: &Parsed) -> usize {
monkey_business::<10_000, 1>(parsed)
}
fn monkey_business<const ITERATIONS: usize, const STRESS_REDUCTION: usize>(parsed: &Parsed) -> usize {
let lcm = parsed.iter().map(|m| m.div_test).reduce(lcm).unwrap();
println!("lcm: {lcm}");
let mut monkeys: Vec<Monkey> = parsed.clone();
let mut moved = Vec::new();
for _ in 0..ITERATIONS {
let mut i = 0;
while i < monkeys.len() {
let monkey = monkeys.get_mut(i).unwrap();
monkey.inspection_count += monkey.items.len();
while !monkey.items.is_empty() {
moved.extend(monkey.items.drain(..).map(|mut stress| {
stress = match monkey.op {
MonkeyOp::Add(x, y) => x.unwrap_or(stress) + y.unwrap_or(stress),
MonkeyOp::Mul(x, y) => x.unwrap_or(stress) * y.unwrap_or(stress),
} / STRESS_REDUCTION;
if stress > lcm {
stress %= lcm;
}
(stress, if stress % monkey.div_test == 0 { monkey.true_dst } else { monkey.false_dst })
}));
}
drop(monkey);
for (item, dst) in moved.drain(..) {
monkeys.get_mut(dst).unwrap().items.push(item);
}
i += 1;
}
}
monkeys.sort_by_key(|m| m.inspection_count);
monkeys.into_iter().rev().map(|m| m.inspection_count).take(2).product()
}
boilerplate! {
TEST_INPUT == "\
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",
tests: {
part1: { TEST_INPUT => 10605 },
part2: { TEST_INPUT => 2713310158 },
},
bench1 == 56595,
bench2 == 15693274740,
bench_parse: Vec::len => 8,
}