Solve day 11
This commit is contained in:
parent
4f7ed8d228
commit
6ddb4c4c8f
3 changed files with 228 additions and 0 deletions
55
input/11
Normal file
55
input/11
Normal file
|
@ -0,0 +1,55 @@
|
|||
Monkey 0:
|
||||
Starting items: 75, 63
|
||||
Operation: new = old * 3
|
||||
Test: divisible by 11
|
||||
If true: throw to monkey 7
|
||||
If false: throw to monkey 2
|
||||
|
||||
Monkey 1:
|
||||
Starting items: 65, 79, 98, 77, 56, 54, 83, 94
|
||||
Operation: new = old + 3
|
||||
Test: divisible by 2
|
||||
If true: throw to monkey 2
|
||||
If false: throw to monkey 0
|
||||
|
||||
Monkey 2:
|
||||
Starting items: 66
|
||||
Operation: new = old + 5
|
||||
Test: divisible by 5
|
||||
If true: throw to monkey 7
|
||||
If false: throw to monkey 5
|
||||
|
||||
Monkey 3:
|
||||
Starting items: 51, 89, 90
|
||||
Operation: new = old * 19
|
||||
Test: divisible by 7
|
||||
If true: throw to monkey 6
|
||||
If false: throw to monkey 4
|
||||
|
||||
Monkey 4:
|
||||
Starting items: 75, 94, 66, 90, 77, 82, 61
|
||||
Operation: new = old + 1
|
||||
Test: divisible by 17
|
||||
If true: throw to monkey 6
|
||||
If false: throw to monkey 1
|
||||
|
||||
Monkey 5:
|
||||
Starting items: 53, 76, 59, 92, 95
|
||||
Operation: new = old + 2
|
||||
Test: divisible by 19
|
||||
If true: throw to monkey 4
|
||||
If false: throw to monkey 3
|
||||
|
||||
Monkey 6:
|
||||
Starting items: 81, 61, 75, 89, 70, 92
|
||||
Operation: new = old * old
|
||||
Test: divisible by 3
|
||||
If true: throw to monkey 0
|
||||
If false: throw to monkey 1
|
||||
|
||||
Monkey 7:
|
||||
Starting items: 81, 86, 62, 87
|
||||
Operation: new = old + 8
|
||||
Test: divisible by 13
|
||||
If true: throw to monkey 3
|
||||
If false: throw to monkey 5
|
27
input/11-test
Normal file
27
input/11-test
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
|
146
src/bin/11.rs
Normal file
146
src/bin/11.rs
Normal file
|
@ -0,0 +1,146 @@
|
|||
use std::{collections::VecDeque, fmt, str::FromStr};
|
||||
|
||||
use aoc2022::*;
|
||||
use itertools::Itertools;
|
||||
|
||||
const INPUT: &str = include_str!("../../input/11");
|
||||
|
||||
fn main() {
|
||||
let mut troop = Troop::from_input();
|
||||
troop.play(20, 3);
|
||||
solved_level_1(troop.level());
|
||||
|
||||
let mut troop = Troop::from_input();
|
||||
troop.play(10000, 1);
|
||||
solved_level_2(troop.level());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Troop(Vec<Monkey>);
|
||||
|
||||
impl Troop {
|
||||
fn level(&self) -> usize {
|
||||
let mut inspections = self.0.iter().map(|m| m.inspected).collect_vec();
|
||||
inspections.sort();
|
||||
inspections.reverse();
|
||||
inspections[0] * inspections[1]
|
||||
}
|
||||
|
||||
fn play(&mut self, rounds: usize, divider: u64) {
|
||||
for _ in 0..rounds {
|
||||
for monkey in 0..self.0.len() {
|
||||
self.monkey_play(monkey, divider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn monkey_play(&mut self, monkey: usize, divider: u64) {
|
||||
self.0[monkey].inspected += self.0[monkey].items.len();
|
||||
|
||||
let modulus: u64 = self.0.iter().map(|m| m.test).product();
|
||||
|
||||
while let Some(mut item) = self.0[monkey].items.pop_front() {
|
||||
let target = {
|
||||
let monkey = &self.0[monkey];
|
||||
match monkey.op {
|
||||
Operation::Add(n) => item += n,
|
||||
Operation::Mul(n) => item *= n,
|
||||
Operation::Square => item *= item,
|
||||
};
|
||||
item /= divider;
|
||||
|
||||
item %= modulus;
|
||||
|
||||
if item % monkey.test == 0 {
|
||||
monkey.throw_true
|
||||
} else {
|
||||
monkey.throw_false
|
||||
}
|
||||
};
|
||||
|
||||
self.0[target].items.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
fn from_input() -> Self {
|
||||
let mut monkeys = Vec::new();
|
||||
// Placeholder while building.
|
||||
let mut current = Monkey {
|
||||
items: VecDeque::new(),
|
||||
op: Operation::Add(0u8.into()),
|
||||
test: 0,
|
||||
throw_true: 0,
|
||||
throw_false: 0,
|
||||
inspected: 0,
|
||||
};
|
||||
|
||||
for (i, line) in INPUT.lines().enumerate() {
|
||||
match i % 7 {
|
||||
0 | 6 => { /* Monkey index or empty line can be ignored */ }
|
||||
1 => {
|
||||
let (_, items) = line.split_once(": ").unwrap();
|
||||
current.items = items
|
||||
.split(", ")
|
||||
.map(|item| item.parse().unwrap())
|
||||
.collect();
|
||||
}
|
||||
2 => {
|
||||
current.op = if line.contains("old * old") {
|
||||
Operation::Square
|
||||
} else if line.contains('*') {
|
||||
Operation::Mul(line.parse_last())
|
||||
} else {
|
||||
Operation::Add(line.parse_last())
|
||||
}
|
||||
}
|
||||
3 => current.test = line.parse_last(),
|
||||
4 => current.throw_true = line.parse_last(),
|
||||
5 => {
|
||||
current.throw_false = line.parse_last();
|
||||
// This is the final line
|
||||
monkeys.push(current.clone());
|
||||
}
|
||||
i => unreachable!("{i} is impossible to get in mod 7"),
|
||||
}
|
||||
}
|
||||
|
||||
Self(monkeys)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Monkey {
|
||||
items: VecDeque<u64>,
|
||||
op: Operation,
|
||||
test: u64,
|
||||
throw_true: usize,
|
||||
throw_false: usize,
|
||||
inspected: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Operation {
|
||||
Add(u64),
|
||||
Mul(u64),
|
||||
Square,
|
||||
}
|
||||
|
||||
/// Helper trait to make code more readable.
|
||||
/// Parses the last element from a whitespace separated str.
|
||||
trait ParseLast<T> {
|
||||
fn parse_last(self) -> T;
|
||||
}
|
||||
|
||||
impl<'a, T> ParseLast<T> for &'a str
|
||||
where
|
||||
T: FromStr,
|
||||
T::Err: fmt::Debug,
|
||||
{
|
||||
fn parse_last(self) -> T {
|
||||
self.split_ascii_whitespace()
|
||||
.last()
|
||||
.unwrap()
|
||||
.parse()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue