use std::collections::VecDeque; #[derive(Debug, Clone)] struct Monkey { id: usize, items: VecDeque, operation: String, divisor: u64, true_monkey: usize, false_monkey: usize, inspected: usize, } fn main() { let contents = std::fs::read_to_string("data.txt").expect("Failed to read file"); let mut monkeys = parse(contents.lines().collect()); let mut monkeys2 = monkeys.clone(); let mut items = monkeys .clone() .into_iter() .map(|m| m.items) .collect::>>(); let mut items2 = items.clone(); // Part 1 run(&mut monkeys, &mut items, 3, 20); // Part 2 run(&mut monkeys2, &mut items2, 1, 10000); } fn run(monkeys: &mut Vec, items: &mut Vec>, divisor: u64, rounds: usize) -> () { let total_prod = monkeys.iter().fold(1, |acc, m| m.divisor * acc); for _ in 1..=rounds { for m in 0..monkeys.len() { let monkey = &mut monkeys[m]; for _ in 0..items[m].len() { let item = items[m].pop_front().unwrap(); let new_item = operate(monkey.operation.as_str(), &item) % total_prod; let new_item = new_item / divisor; monkey.inspected += 1; if new_item % monkey.divisor == 0 { items[monkey.true_monkey].push_back(new_item); } else { items[monkey.false_monkey].push_back(new_item); } } } } let mut active = monkeys.iter().map(|m| m.inspected).collect::>(); active.sort(); active.reverse(); let score = active.drain(0..2).fold(1, |acc, x| acc * x); println!("\nactive: {:?}", active); println!("score: {score}"); } fn parse(lines: Vec<&str>) -> Vec { lines .chunks(7) .into_iter() .map(|lines| { let items = lines[1] .split(" ") .skip(4) .map(|i| i.get(0..2).unwrap().parse().unwrap()) .collect::>(); let operation = lines[2].split("=").collect::>()[1] .trim() .to_string(); let divisor = lines[3].split(" ").last().unwrap().parse().unwrap(); let true_monkey = lines[4].chars().last().unwrap().to_digit(10).unwrap() as usize; let false_monkey = lines[5].chars().last().unwrap().to_digit(10).unwrap() as usize; Monkey { id: lines[0].chars().nth(7).unwrap().to_digit(10).unwrap() as usize, items, operation, divisor, true_monkey, false_monkey, inspected: 0, } }) .collect() } fn operate(eq: &str, item: &u64) -> u64 { match eq.split(" ").collect::>().as_slice() { ["old", "*", "old"] => item * item, ["old", "*", x] => item * x.parse::().unwrap(), ["old", "+", x] => item + x.parse::().unwrap(), _ => panic!("Invalid operation"), } }