advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.rs (5747B)

    1 use regex::Regex;
    2 use std::collections::{BinaryHeap, HashMap};
    3 
    4 #[derive(Debug, Clone)]
    5 enum Op {
    6     Mult(i64),
    7     MultSelf,
    8     Add(i64),
    9     AddSelf,
   10 }
   11 
   12 impl Op {
   13     fn from_str(s: &str) -> Option<Self> {
   14         if let Some(cap) =
   15             Regex::new(r"^  Operation: new = old (?P<op>[\*\+]) (?P<target>(old|[-0-9]+))$")
   16                 .unwrap()
   17                 .captures(s)
   18         {
   19             match (
   20                 cap.name("op").unwrap().as_str(),
   21                 cap.name("target").unwrap().as_str(),
   22             ) {
   23                 ("*", "old") => Some(Self::MultSelf),
   24                 ("*", target) => Some(Self::Mult(target.parse::<i64>().unwrap())),
   25                 ("+", "old") => Some(Self::AddSelf),
   26                 ("+", target) => Some(Self::Add(target.parse::<i64>().unwrap())),
   27                 _ => None,
   28             }
   29         } else {
   30             None
   31         }
   32     }
   33 
   34     fn exec(&self, old: i64) -> i64 {
   35         match self {
   36             Self::MultSelf => old * old,
   37             Self::Mult(x) => old * x,
   38             Self::AddSelf => old + old,
   39             Self::Add(x) => old + x,
   40         }
   41     }
   42 }
   43 
   44 #[derive(Debug, Clone)]
   45 struct Monkey {
   46     id: usize,
   47     items: Vec<i64>,
   48     op: Op,
   49     test: i64,
   50     id_true: usize,
   51     id_false: usize,
   52 }
   53 
   54 impl Monkey {
   55     fn from_str(s: &str) -> Option<Self> {
   56         let mut ss = s.trim().split('\n');
   57         if let (Some(cap_1), Some(cap_2), Some(op), Some(cap_3), Some(cap_4), Some(cap_5)) = (
   58             Regex::new(r"^Monkey (?P<id>[0-9]+):$")
   59                 .unwrap()
   60                 .captures(ss.next().unwrap()),
   61             Regex::new(r"^  Starting items: (?P<items>[0-9 ,]+)$")
   62                 .unwrap()
   63                 .captures(ss.next().unwrap()),
   64             Op::from_str(ss.next().unwrap()),
   65             Regex::new(r"^  Test: divisible by (?P<test>[0-9]+)$")
   66                 .unwrap()
   67                 .captures(ss.next().unwrap()),
   68             Regex::new(r"^    If true: throw to monkey (?P<id_true>[0-9]+)$")
   69                 .unwrap()
   70                 .captures(ss.next().unwrap()),
   71             Regex::new(r"^    If false: throw to monkey (?P<id_false>[0-9]+)$")
   72                 .unwrap()
   73                 .captures(ss.next().unwrap()),
   74         ) {
   75             let m = Monkey {
   76                 id: cap_1.name("id").unwrap().as_str().parse::<usize>().unwrap(),
   77                 items: cap_2
   78                     .name("items")
   79                     .unwrap()
   80                     .as_str()
   81                     .split(", ")
   82                     .map(|x| x.parse::<i64>().unwrap())
   83                     .collect(),
   84                 op: op,
   85                 test: cap_3.name("test").unwrap().as_str().parse::<i64>().unwrap(),
   86                 id_true: cap_4
   87                     .name("id_true")
   88                     .unwrap()
   89                     .as_str()
   90                     .parse::<usize>()
   91                     .unwrap(),
   92                 id_false: cap_5
   93                     .name("id_false")
   94                     .unwrap()
   95                     .as_str()
   96                     .parse::<usize>()
   97                     .unwrap(),
   98             };
   99             Some(m)
  100         } else {
  101             None
  102         }
  103     }
  104 }
  105 
  106 fn main() {
  107     let input: Vec<Monkey> = std::fs::read_to_string("input.txt")
  108         .unwrap()
  109         .trim()
  110         .split("\n\n")
  111         .map(|x| Monkey::from_str(x).unwrap())
  112         .collect();
  113     // 119715
  114     println!("Part 1: {}", part_1(&input, 20));
  115     // 18085004878
  116     println!("Part 2: {}", part_2(&input, 10000));
  117 }
  118 
  119 fn part_1(input: &Vec<Monkey>, rounds: usize) -> i64 {
  120     let mut inspect_count = HashMap::new();
  121     let mut monkeys = (*input).clone();
  122     for _ in 0..rounds {
  123         for i in 0..monkeys.len() {
  124             let mut item_idx = 0;
  125             let item_count = monkeys[i].items.len();
  126             while item_idx < item_count {
  127                 let worry_new = monkeys[i].op.exec(monkeys[i].items[item_idx]) / 3;
  128                 inspect_count.insert(
  129                     monkeys[i].id,
  130                     *inspect_count.get(&monkeys[i].id).unwrap_or(&0) + 1,
  131                 );
  132                 let new_id = if worry_new % monkeys[i].test == 0 {
  133                     monkeys[i].id_true
  134                 } else {
  135                     monkeys[i].id_false
  136                 };
  137                 monkeys[new_id].items.push(worry_new);
  138                 item_idx += 1;
  139             }
  140             monkeys[i].items.clear();
  141         }
  142     }
  143     let mut monkey_business = BinaryHeap::from_iter(inspect_count.values());
  144     monkey_business.pop().unwrap() * monkey_business.pop().unwrap()
  145 }
  146 
  147 fn part_2(input: &Vec<Monkey>, rounds: usize) -> i64 {
  148     let mut inspect_count = HashMap::new();
  149     let mut monkeys = (*input).clone();
  150     let mod_factor = monkeys.iter().map(|m| m.test).product::<i64>();
  151     for _ in 0..rounds {
  152         for i in 0..monkeys.len() {
  153             let mut item_idx = 0;
  154             let item_count = monkeys[i].items.len();
  155             while item_idx < item_count {
  156                 let worry_new = monkeys[i].op.exec(monkeys[i].items[item_idx]) % mod_factor;
  157                 inspect_count.insert(
  158                     monkeys[i].id,
  159                     *inspect_count.get(&monkeys[i].id).unwrap_or(&0) + 1,
  160                 );
  161                 let new_id = if worry_new % monkeys[i].test == 0 {
  162                     monkeys[i].id_true
  163                 } else {
  164                     monkeys[i].id_false
  165                 };
  166                 monkeys[new_id].items.push(worry_new);
  167                 item_idx += 1;
  168             }
  169             monkeys[i].items.clear();
  170         }
  171     }
  172     let mut monkey_business = BinaryHeap::from_iter(inspect_count.values());
  173     monkey_business.pop().unwrap() * monkey_business.pop().unwrap()
  174 }