2022 - Day 11

This commit is contained in:
Dreaded_X 2022-12-11 17:33:10 +01:00
parent 6d87bd24ad
commit afd943fcd7
3 changed files with 258 additions and 0 deletions

55
2022/input/11/input Normal file
View File

@ -0,0 +1,55 @@
Monkey 0:
Starting items: 52, 60, 85, 69, 75, 75
Operation: new = old * 17
Test: divisible by 13
If true: throw to monkey 6
If false: throw to monkey 7
Monkey 1:
Starting items: 96, 82, 61, 99, 82, 84, 85
Operation: new = old + 8
Test: divisible by 7
If true: throw to monkey 0
If false: throw to monkey 7
Monkey 2:
Starting items: 95, 79
Operation: new = old + 6
Test: divisible by 19
If true: throw to monkey 5
If false: throw to monkey 3
Monkey 3:
Starting items: 88, 50, 82, 65, 77
Operation: new = old * 19
Test: divisible by 2
If true: throw to monkey 4
If false: throw to monkey 1
Monkey 4:
Starting items: 66, 90, 59, 90, 87, 63, 53, 88
Operation: new = old + 7
Test: divisible by 5
If true: throw to monkey 1
If false: throw to monkey 0
Monkey 5:
Starting items: 92, 75, 62
Operation: new = old * old
Test: divisible by 3
If true: throw to monkey 3
If false: throw to monkey 4
Monkey 6:
Starting items: 94, 86, 76, 67
Operation: new = old + 1
Test: divisible by 11
If true: throw to monkey 5
If false: throw to monkey 2
Monkey 7:
Starting items: 57
Operation: new = old + 2
Test: divisible by 17
If true: throw to monkey 6
If false: throw to monkey 2

27
2022/input/11/test-1 Normal file
View File

@ -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

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

@ -0,0 +1,176 @@
#![feature(test)]
use std::{str::FromStr, cmp::{min, max}};
use anyhow::Result;
use aoc::Solver;
// -- Runners --
fn main() -> Result<()> {
Day::solve()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_test1() -> Result<()> {
Day::test(Day::part1, "test-1", 10605)
}
#[test]
fn part1_solution() -> Result<()> {
Day::test(Day::part1, "input", 95472)
}
#[test]
fn part2_test1() -> Result<()> {
Day::test(Day::part2, "test-1", 2713310158)
}
#[test]
fn part2_solution() -> Result<()> {
Day::test(Day::part2, "input", 17926061332)
}
// Benchmarks
extern crate test;
#[bench]
#[ignore]
fn part1_bench(b: &mut test::Bencher) {
Day::benchmark(Day::part1, b)
}
#[bench]
#[ignore]
fn part2_bench(b: &mut test::Bencher) {
Day::benchmark(Day::part2, b)
}
}
fn gcd(a: i64, b: i64) -> i64 {
match ((a, b), (a & 1, b & 1)) {
((x, y), _) if x == y => y,
((0, x), _) | ((x, 0), _) => x,
((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y),
((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1,
((x, y), (1, 1)) => {
let (x, y) = (min(x, y), max(x, y));
gcd((y - x) >> 1, x)
}
_ => unreachable!(),
}
}
fn lcm(a: i64, b: i64) -> i64 {
a * b / gcd(a, b)
}
#[derive(Debug, Copy, Clone)]
enum Operation {
Add(i64),
AddOld,
Multiply(i64),
MultiplyOld,
}
impl FromStr for Operation {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let operation = s.split(" ").collect::<Vec<_>>();
match operation.as_slice() {
["old", "*", "old"] => Ok(Operation::MultiplyOld),
["old", "*", value] => Ok(Operation::Multiply(value.parse()?)),
["old", "+", "old"] => Ok(Operation::AddOld),
["old", "+", value] => Ok(Operation::Add(value.parse()?)),
_ => Err(anyhow::anyhow!("Invalid input")),
}
}
}
#[derive(Debug)]
struct Monkey {
items: Vec<i64>,
operation: Operation,
divisor: i64,
next: (usize, usize),
inspects: i64,
}
impl FromStr for Monkey {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lines = s.lines().collect::<Vec<_>>();
let items = lines[1].split_once(": ").unwrap().1.split(", ").map(|num| num.parse().unwrap()).collect();
let operation: Operation = lines[2].split_once("= ").unwrap().1.parse()?;
let divisor = lines[3].rsplit_once(" ").unwrap().1.parse()?;
let next_true = lines[4].rsplit_once(" ").unwrap().1.parse()?;
let next_false = lines[5].rsplit_once(" ").unwrap().1.parse()?;
Ok(Self {items, operation, divisor, next: (next_true, next_false), inspects: 0})
}
}
fn step(monkeys: &mut Vec<Monkey>, div: i64, reducer: i64) {
for idx in 0..monkeys.len() {
let items = std::mem::take(&mut monkeys[idx].items);
for item in items {
// Calculate the new item value
let mut i = match monkeys[idx].operation {
Operation::Add(v) => item + v,
Operation::AddOld => item + item,
Operation::Multiply(v) => item * v,
Operation::MultiplyOld => item * item,
} / div;
i %= reducer;
// Increase the inspect counter for this monkey
monkeys[idx].inspects += 1;
let next;
if i % monkeys[idx].divisor == 0 {
next = monkeys[idx].next.0;
} else {
next = monkeys[idx].next.1;
}
monkeys[next].items.push(i);
}
}
}
fn solution(input: &str, rounds: i32, div: i64) -> i64 {
let mut monkeys: Vec<Monkey> = input.split("\n\n").map(|line| line.parse().unwrap()).collect();
let reducer = monkeys.iter().fold(1, |acc, monkey| lcm(acc, monkey.divisor));
for _ in 0..rounds {
step(&mut monkeys, div, reducer);
}
let mut inspects = monkeys.iter().map(|monkey| monkey.inspects).collect::<Vec<_>>();
inspects.sort();
inspects.into_iter().rev().take(2).reduce(|acc, inspects| acc * inspects).unwrap()
}
// -- Solution --
pub struct Day;
impl aoc::Solver for Day {
type Output1 = i64;
type Output2 = i64;
fn day() -> u8 {
11
}
fn part1(input: &str) -> Self::Output1 {
solution(input, 20, 3)
}
fn part2(input: &str) -> Self::Output2 {
solution(input, 10000, 1)
}
}