struct Monkey { items: Vec, operation: Box i64>, test: Box i64>, inspections: u64, } fn empty_op(_: i64) -> i64 { -1 } fn empty_test(_: i64) -> i64 { -1 } fn op_func(op: char, operand: &str) -> Box i64> { let op = match op { '*' => std::ops::Mul::mul, '+' => std::ops::Add::add, _ => panic!("unsupported op {}", op), }; if operand == "old" { Box::new(move |x| op(x, x)) } else { let operand: i64 = operand.parse().unwrap(); Box::new(move |x| op(x, operand)) } } fn main() { const INPUT: &str = include_str!("../input.txt"); let mut monkeys: Vec = Vec::new(); let mut cur_monkey = -1i64; let mut cur_test_divisor = -1i64; let mut cur_test_true_ret = -1i64; let mut lcm: i64 = 1; for line in INPUT.lines() { let line = line.trim_start(); if line == "" { continue; } else if line.starts_with("Monkey") { cur_monkey += 1; monkeys.push(Monkey { items: Vec::new(), operation: Box::new(empty_op), test: Box::new(empty_test), inspections: 0, }); continue; } else if line.starts_with("Starting items: ") { let items = line[16..].split(", "); for item in items { monkeys[cur_monkey as usize] .items .push(item.parse().unwrap()); } } else if line.starts_with("Operation: ") { let mut items = line[21..].split(' '); let op = items.next().unwrap().chars().next().unwrap(); let operand = items.next().unwrap(); monkeys[cur_monkey as usize].operation = op_func(op, operand); } else if line.starts_with("Test: ") { cur_test_divisor = line[19..].parse().unwrap(); lcm = num::integer::lcm(lcm, cur_test_divisor); } else if line.starts_with("If true: ") { cur_test_true_ret = line[25..].parse().unwrap(); } else if line.starts_with("If false: ") { let target: i64 = line[26..].parse().unwrap(); monkeys[cur_monkey as usize].test = Box::new(move |x| { if x % cur_test_divisor == 0 { cur_test_true_ret } else { target } }); } } println!("lcm: {}", lcm); for _ in 1..=10000 { for i in 0..monkeys.len() { for j in 0..monkeys[i].items.len() { let mut new_worry = (monkeys[i].operation)(monkeys[i].items[j]); new_worry = new_worry % lcm; let dest: usize = (monkeys[i].test)(new_worry).try_into().unwrap(); monkeys[dest].items.push(new_worry); monkeys[i].inspections += 1; } monkeys[i].items.clear(); } } let mut active_monkeys = monkeys.iter().map(|m| m.inspections).collect::>(); active_monkeys.sort(); active_monkeys.reverse(); println!("{}", active_monkeys[0] * active_monkeys[1]); }