2022 - Day 11
This commit is contained in:
parent
6d87bd24ad
commit
afd943fcd7
55
2022/input/11/input
Normal file
55
2022/input/11/input
Normal 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
27
2022/input/11/test-1
Normal 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
176
2022/src/bin/day11.rs
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user