Day 11, puzzle 1
This commit is contained in:
22
src/bin/d11p1.rs
Normal file
22
src/bin/d11p1.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use aoc22::{
|
||||
day11::{self, monkey_business},
|
||||
util,
|
||||
};
|
||||
|
||||
const N_ROUNDS: usize = 20;
|
||||
|
||||
pub fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let monkeys = day11::parse_monkeys(&util::parse_input());
|
||||
|
||||
for _ in 0..20 {
|
||||
day11::do_round(&monkeys);
|
||||
}
|
||||
|
||||
println!(
|
||||
"Monkey business after {} rounds is {}",
|
||||
N_ROUNDS,
|
||||
monkey_business(&monkeys)
|
||||
);
|
||||
}
|
||||
199
src/day11.rs
Normal file
199
src/day11.rs
Normal file
@ -0,0 +1,199 @@
|
||||
use std::{borrow::BorrowMut, cell::RefCell, collections::VecDeque};
|
||||
|
||||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OpKind {
|
||||
Add,
|
||||
Mul,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OpParam {
|
||||
Old,
|
||||
Num(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Operation {
|
||||
pub kind: OpKind,
|
||||
pub a: OpParam,
|
||||
pub b: OpParam,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Test {
|
||||
pub div: usize,
|
||||
pub target_true: usize,
|
||||
pub target_false: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Monkey {
|
||||
pub activity: usize,
|
||||
pub items: VecDeque<usize>,
|
||||
pub op: Operation,
|
||||
pub test: Test,
|
||||
}
|
||||
|
||||
pub fn parse_monkeys(input: &String) -> Vec<RefCell<Monkey>> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
for (n, monkey) in input.lines().chunks(7).into_iter().enumerate() {
|
||||
let (n_actual, monkey) = parse_monkey(&monkey.collect());
|
||||
assert_eq!(n, n_actual);
|
||||
result.push(RefCell::new(monkey));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn parse_monkey(lines: &Vec<&str>) -> (usize, Monkey) {
|
||||
let re0 = Regex::new(r"^Monkey (\d)+:$").unwrap();
|
||||
let re1 = Regex::new(r"^ Starting items: ((\d+(?:, )?)+)$").unwrap();
|
||||
let re2 = Regex::new(r"^ Operation: new = (old|\d+) ([*+]) (old|\d+)$").unwrap();
|
||||
let re3 = Regex::new(r"^ Test: divisible by (\d+)$").unwrap();
|
||||
let re45 = Regex::new(r"^ If (true|false): throw to monkey (\d+)$").unwrap();
|
||||
|
||||
let n: usize = re0
|
||||
.captures(lines.get(0).unwrap())
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let items = re1
|
||||
.captures(lines.get(1).unwrap())
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.split(", ")
|
||||
.map(|i| i.parse().expect(&format!("Invalid item: {}", i)))
|
||||
.collect();
|
||||
|
||||
let op = re2.captures(lines.get(2).unwrap()).unwrap();
|
||||
let op_a = parse_op_param(op.get(1).unwrap().as_str());
|
||||
let op_kind = parse_op_kind(op.get(2).unwrap().as_str());
|
||||
let op_b = parse_op_param(op.get(3).unwrap().as_str());
|
||||
let op = Operation {
|
||||
kind: op_kind,
|
||||
a: op_a,
|
||||
b: op_b,
|
||||
};
|
||||
|
||||
let test_div = re3
|
||||
.captures(lines.get(3).unwrap())
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let test_true = re45.captures(lines.get(4).unwrap()).unwrap();
|
||||
assert_eq!(test_true.get(1).unwrap().as_str(), "true");
|
||||
let test_true = test_true.get(2).unwrap().as_str().parse().unwrap();
|
||||
|
||||
let test_false = re45.captures(lines.get(5).unwrap()).unwrap();
|
||||
assert_eq!(test_false.get(1).unwrap().as_str(), "false");
|
||||
let test_false = test_false.get(2).unwrap().as_str().parse().unwrap();
|
||||
|
||||
let test = Test {
|
||||
div: test_div,
|
||||
target_true: test_true,
|
||||
target_false: test_false,
|
||||
};
|
||||
|
||||
assert!(lines.len() == 6 || lines.get(6).unwrap().is_empty());
|
||||
|
||||
(
|
||||
n,
|
||||
Monkey {
|
||||
activity: 0,
|
||||
items,
|
||||
op,
|
||||
test,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_op_param(s: &str) -> OpParam {
|
||||
if s == "old" {
|
||||
OpParam::Old
|
||||
} else {
|
||||
OpParam::Num(s.parse().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_op_kind(s: &str) -> OpKind {
|
||||
match s {
|
||||
"+" => OpKind::Add,
|
||||
"*" => OpKind::Mul,
|
||||
_ => panic!("Unknown OpKind {}", s),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_round(monkeys: &Vec<RefCell<Monkey>>) {
|
||||
for n in 0..monkeys.len() {
|
||||
let mut monkey = monkeys.get(n).unwrap().borrow_mut();
|
||||
log::debug!("Monkey {}", n);
|
||||
while !monkey.items.is_empty() {
|
||||
monkey.activity += 1;
|
||||
let mut item = monkey.items.pop_front().unwrap();
|
||||
log::debug!(" Monkey inspects an item with a worry level of {}.", item);
|
||||
item = run_op(&monkey.op, item);
|
||||
log::debug!(" Worry level increases to {}.", item);
|
||||
item /= 3;
|
||||
log::debug!(
|
||||
" Monkey gets bored with item. Worry level is divided by 3 to {}.",
|
||||
item
|
||||
);
|
||||
let target = if item % monkey.test.div == 0 {
|
||||
log::debug!(
|
||||
"Current worry level is not divisible by {}",
|
||||
monkey.test.div
|
||||
);
|
||||
monkey.test.target_true
|
||||
} else {
|
||||
log::debug!("Current worry level is divisible by {}", monkey.test.div);
|
||||
monkey.test.target_false
|
||||
};
|
||||
log::debug!(
|
||||
"Item with worry level {} is thrown to monkey {}.",
|
||||
item,
|
||||
target
|
||||
);
|
||||
let mut target = &mut monkeys.get(target).unwrap().borrow_mut().items;
|
||||
target.push_back(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_op(op: &Operation, item: usize) -> usize {
|
||||
let a = match op.a {
|
||||
OpParam::Old => item,
|
||||
OpParam::Num(n) => n,
|
||||
};
|
||||
let b = match op.b {
|
||||
OpParam::Old => item,
|
||||
OpParam::Num(n) => n,
|
||||
};
|
||||
match op.kind {
|
||||
OpKind::Add => a + b,
|
||||
OpKind::Mul => a * b,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn monkey_business(monkeys: &Vec<RefCell<Monkey>>) -> usize {
|
||||
monkeys
|
||||
.iter()
|
||||
.map(|m| m.borrow().activity)
|
||||
.sorted()
|
||||
.rev()
|
||||
.take(2)
|
||||
.product()
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
pub mod day1;
|
||||
pub mod day10;
|
||||
pub mod day11;
|
||||
pub mod day2;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
|
||||
Reference in New Issue
Block a user