Explorar el Código

day11 AND REALLY COOL MATH

Jake Fenton hace 1 año
padre
commit
9bc25f042f
Se han modificado 2 ficheros con 167 adiciones y 0 borrados
  1. 140 0
      src/bin/11.rs
  2. 27 0
      src/examples/11.txt

+ 140 - 0
src/bin/11.rs

@@ -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));
+    }
+}

+ 27 - 0
src/examples/11.txt

@@ -0,0 +1,27 @@
+Monkey 0:
+  Starting items: 79, 98
+  Operation: new = old * 19
+  Test: divisible by 23
+    If true: throw to monkey 2
+    If false: throw to monkey 3
+
+Monkey 1:
+  Starting items: 54, 65, 75, 74
+  Operation: new = old + 6
+  Test: divisible by 19
+    If true: throw to monkey 2
+    If false: throw to monkey 0
+
+Monkey 2:
+  Starting items: 79, 60, 97
+  Operation: new = old * old
+  Test: divisible by 13
+    If true: throw to monkey 1
+    If false: throw to monkey 3
+
+Monkey 3:
+  Starting items: 74
+  Operation: new = old + 3
+  Test: divisible by 17
+    If true: throw to monkey 0
+    If false: throw to monkey 1