|
@@ -0,0 +1,140 @@
|
|
|
+#![feature(get_many_mut)]
|
|
|
+pub struct Monkey {
|
|
|
+ items: Vec<u128>,
|
|
|
+ num_inspected: u64,
|
|
|
+ false_target: usize,
|
|
|
+ true_target: usize,
|
|
|
+ mutation_func: Box<dyn Fn(u128) -> u128>,
|
|
|
+ test_val: u128
|
|
|
+}
|
|
|
+
|
|
|
+pub fn parse_mutation(mutation: &str) -> Box<dyn Fn(u128) -> u128> {
|
|
|
+ if mutation.contains("+") {
|
|
|
+ let (_, right) = mutation.split_once("+ ").unwrap();
|
|
|
+ // left is always old
|
|
|
+ if right.trim().starts_with("o") {
|
|
|
+ return Box::new(|item| item + item);
|
|
|
+ } else {
|
|
|
+ let value: u128 = right.parse().unwrap();
|
|
|
+ return Box::new(move |item| item + value);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ let (_, right) = mutation.split_once("* ").unwrap();
|
|
|
+ // left is always old
|
|
|
+ if right.trim().starts_with("o") {
|
|
|
+ return Box::new(|item| item * item);
|
|
|
+ } else {
|
|
|
+ let value: u128 = right.parse().unwrap();
|
|
|
+ return Box::new(move |item| item * value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+pub fn parse_input(input: &str) -> Vec<Monkey>{
|
|
|
+ let mut lines = input.lines();
|
|
|
+ let mut monkeys: Vec<Monkey> = Vec::new();
|
|
|
+
|
|
|
+ while let Some(l) = lines.next() {
|
|
|
+ // l is monkeyname, don't care
|
|
|
+ let starting_items: Vec<u128> = lines.next().unwrap().split_once(": ").unwrap().1.split(",").map(|s| s.trim().parse().unwrap()).collect();
|
|
|
+ let mutation = parse_mutation(lines.next().unwrap().split_once("=").unwrap().1);
|
|
|
+ let test_val = lines.next().unwrap().split(" ").last().unwrap().parse().unwrap();
|
|
|
+ let true_target: usize = lines.next().unwrap().split(" ").last().unwrap().parse().unwrap();
|
|
|
+ let false_target: usize = lines.next().unwrap().split(" ").last().unwrap().parse().unwrap();
|
|
|
+ monkeys.push(Monkey {
|
|
|
+ items: starting_items,
|
|
|
+ num_inspected: 0,
|
|
|
+ false_target: false_target,
|
|
|
+ true_target: true_target,
|
|
|
+ mutation_func: mutation,
|
|
|
+ test_val: test_val
|
|
|
+ });
|
|
|
+ match lines.next() {
|
|
|
+ Some(_) => {},
|
|
|
+ _ => { break;}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ monkeys
|
|
|
+}
|
|
|
+
|
|
|
+pub fn part_one(input: &str) -> Option<u64> {
|
|
|
+ let mut monkeys = parse_input(input);
|
|
|
+ for _round in 0..20 {
|
|
|
+ for monkey_idx in 0..monkeys.len() {
|
|
|
+ let true_monkey_idx = monkeys[monkey_idx].true_target;
|
|
|
+ let false_monkey_idx = monkeys[monkey_idx].false_target;
|
|
|
+ let [our_monkey, true_monkey, false_monkey] = monkeys.get_many_mut([
|
|
|
+ monkey_idx,
|
|
|
+ true_monkey_idx,
|
|
|
+ false_monkey_idx
|
|
|
+ ]).unwrap();
|
|
|
+ for item in our_monkey.items.iter() {
|
|
|
+ let new_worry = our_monkey.mutation_func.as_ref()(*item) / 3;
|
|
|
+ our_monkey.num_inspected += 1;
|
|
|
+ if new_worry % our_monkey.test_val == 0 {
|
|
|
+ true_monkey.items.push(new_worry);
|
|
|
+ } else {
|
|
|
+ false_monkey.items.push(new_worry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ our_monkey.items.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let mut monkey_activity_levels: Vec<u64> = monkeys.iter().map(|m| m.num_inspected).collect();
|
|
|
+ monkey_activity_levels.sort();
|
|
|
+ monkey_activity_levels.reverse();
|
|
|
+ Some((monkey_activity_levels[0] * monkey_activity_levels[1]).into())
|
|
|
+}
|
|
|
+
|
|
|
+pub fn part_two(input: &str) -> Option<u128> {
|
|
|
+ let mut monkeys = parse_input(input);
|
|
|
+ let mod_factor = monkeys.iter().fold(1, |acc, m| acc * m.test_val);
|
|
|
+ for _round in 0..10000 {
|
|
|
+ for monkey_idx in 0..monkeys.len() {
|
|
|
+ let true_monkey_idx = monkeys[monkey_idx].true_target;
|
|
|
+ let false_monkey_idx = monkeys[monkey_idx].false_target;
|
|
|
+ let [our_monkey, true_monkey, false_monkey] = monkeys.get_many_mut([
|
|
|
+ monkey_idx,
|
|
|
+ true_monkey_idx,
|
|
|
+ false_monkey_idx
|
|
|
+ ]).unwrap();
|
|
|
+ for item in our_monkey.items.iter() {
|
|
|
+ let new_worry = our_monkey.mutation_func.as_ref()(*item) % mod_factor;
|
|
|
+ our_monkey.num_inspected += 1;
|
|
|
+ if new_worry % our_monkey.test_val == 0 {
|
|
|
+ true_monkey.items.push(new_worry);
|
|
|
+ } else {
|
|
|
+ false_monkey.items.push(new_worry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ our_monkey.items.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let mut monkey_activity_levels: Vec<u64> = monkeys.iter().map(|m| m.num_inspected).collect();
|
|
|
+ monkey_activity_levels.sort();
|
|
|
+ monkey_activity_levels.reverse();
|
|
|
+ Some((monkey_activity_levels[0] * monkey_activity_levels[1]).into())
|
|
|
+}
|
|
|
+
|
|
|
+fn main() {
|
|
|
+ let input = &advent_of_code::read_file("inputs", 11);
|
|
|
+ advent_of_code::solve!(1, part_one, input);
|
|
|
+ advent_of_code::solve!(2, part_two, input);
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod tests {
|
|
|
+ use super::*;
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_part_one() {
|
|
|
+ let input = advent_of_code::read_file("examples", 11);
|
|
|
+ assert_eq!(part_one(&input), Some(10605));
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn test_part_two() {
|
|
|
+ let input = advent_of_code::read_file("examples", 11);
|
|
|
+ assert_eq!(part_two(&input), Some(2713310158));
|
|
|
+ }
|
|
|
+}
|