Add day 11
This commit is contained in:
127
src/day11/main.rs
Normal file
127
src/day11/main.rs
Normal file
@ -0,0 +1,127 @@
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use base::read_file;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum Op {
|
||||
Add(u64),
|
||||
Multiply(u64),
|
||||
MultiplySelf,
|
||||
}
|
||||
|
||||
impl FromStr for Op {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut iter = s.split_whitespace();
|
||||
let _ = iter.next();
|
||||
let op = iter.next().ok_or(())?.chars().next().ok_or(())?;
|
||||
let value = iter.next().ok_or(())?;
|
||||
if value == "old" && op == '*' {
|
||||
return Ok(Op::MultiplySelf);
|
||||
}
|
||||
let value = value.parse::<u64>().ok().ok_or(())?;
|
||||
return match op {
|
||||
'+' => Ok(Op::Add(value)),
|
||||
'*' => Ok(Op::Multiply(value)),
|
||||
_ => Err(())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Monkey {
|
||||
id: usize,
|
||||
items: Vec<u64>,
|
||||
operation: Op,
|
||||
test_value: u64,
|
||||
next_success: usize,
|
||||
next_failure: usize,
|
||||
}
|
||||
|
||||
fn do_round<const F: u64>(monkeys: &mut Vec<Monkey>, monkey_counter: &mut HashMap<usize, u64>) {
|
||||
let lcm = monkeys.iter().map(|m| m.test_value).reduce(|acc, item| acc * item).unwrap();
|
||||
let mut items_to_add = HashMap::new();
|
||||
for monkey in monkeys.iter_mut() {
|
||||
if let Some(new_items) = items_to_add.remove(&monkey.id) {
|
||||
for new_item in new_items {
|
||||
monkey.items.push(new_item);
|
||||
}
|
||||
}
|
||||
|
||||
for item in &monkey.items {
|
||||
*monkey_counter.entry(monkey.id).or_insert_with(|| 0) += 1;
|
||||
let worry_level = match monkey.operation {
|
||||
Op::Add(x) => *item + x,
|
||||
Op::Multiply(x) => *item * x,
|
||||
Op::MultiplySelf => *item * *item
|
||||
} / F;
|
||||
let worry_level = worry_level % lcm;
|
||||
|
||||
let test_successful = worry_level % monkey.test_value == 0;
|
||||
items_to_add.entry(if test_successful {
|
||||
monkey.next_success
|
||||
} else {
|
||||
monkey.next_failure
|
||||
}).or_insert_with(|| Vec::new()).push(worry_level);
|
||||
}
|
||||
|
||||
monkey.items.clear();
|
||||
}
|
||||
for monkey in monkeys.iter_mut() {
|
||||
if let Some(new_items) = items_to_add.remove(&monkey.id) {
|
||||
for new_item in new_items {
|
||||
monkey.items.push(new_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = read_file("day11.txt");
|
||||
|
||||
let mut monkeys = vec![];
|
||||
let monkeys_strings = input.chunks(7);
|
||||
|
||||
for monkeys_string in monkeys_strings {
|
||||
let id = monkeys_string[0].replace(":", "").split_whitespace().collect::<Vec<_>>()[1].parse::<usize>().unwrap();
|
||||
let items = monkeys_string[1].replace(",", "").split_whitespace().skip(2).filter_map(|s| s.parse::<u64>().ok()).collect::<Vec<_>>();
|
||||
let operation = monkeys_string[2].split(" = ").filter_map(|s| s.parse::<Op>().ok()).next().unwrap();
|
||||
let test_value = monkeys_string[3].split_whitespace().filter_map(|s| s.parse::<u64>().ok()).next().unwrap();
|
||||
let next_success = monkeys_string[4].split_whitespace().filter_map(|s| s.parse::<usize>().ok()).next().unwrap();
|
||||
let next_failure = monkeys_string[5].split_whitespace().filter_map(|s| s.parse::<usize>().ok()).next().unwrap();
|
||||
monkeys.push(Monkey {
|
||||
id,
|
||||
items,
|
||||
operation,
|
||||
test_value,
|
||||
next_success,
|
||||
next_failure,
|
||||
})
|
||||
}
|
||||
|
||||
let mut monkey_counter = HashMap::new();
|
||||
|
||||
let mut monkey_copy = monkeys.clone();
|
||||
for _ in 0..20 {
|
||||
do_round::<3>(&mut monkey_copy, &mut monkey_counter);
|
||||
}
|
||||
|
||||
let mut items = monkey_counter.values().collect::<Vec<_>>();
|
||||
items.sort();
|
||||
items.reverse();
|
||||
|
||||
println!("1. Result: {}", items[0] * items[1]);
|
||||
|
||||
monkey_counter.clear();
|
||||
let mut monkey_copy = monkeys.clone();
|
||||
for _ in 0..10000 {
|
||||
do_round::<1>(&mut monkey_copy, &mut monkey_counter);
|
||||
}
|
||||
|
||||
let mut items = monkey_counter.values().collect::<Vec<_>>();
|
||||
items.sort();
|
||||
items.reverse();
|
||||
|
||||
println!("2. Result: {}", items[0] * items[1]);
|
||||
}
|
Reference in New Issue
Block a user