You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.1 KiB
Rust

use std::collections::VecDeque;
#[derive(Debug, Clone)]
struct Monkey {
id: usize,
items: VecDeque<u64>,
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::<Vec<VecDeque<u64>>>();
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<Monkey>, items: &mut Vec<VecDeque<u64>>, 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::<Vec<usize>>();
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<Monkey> {
lines
.chunks(7)
.into_iter()
.map(|lines| {
let items = lines[1]
.split(" ")
.skip(4)
.map(|i| i.get(0..2).unwrap().parse().unwrap())
.collect::<VecDeque<u64>>();
let operation = lines[2].split("=").collect::<Vec<&str>>()[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::<Vec<&str>>().as_slice() {
["old", "*", "old"] => item * item,
["old", "*", x] => item * x.parse::<u64>().unwrap(),
["old", "+", x] => item + x.parse::<u64>().unwrap(),
_ => panic!("Invalid operation"),
}
}