advent-of-code

Perserverance, or the lack thereof

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

main.rs (5175B)

    1 use std::collections::VecDeque;
    2 
    3 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    4 enum Pos {
    5     Left,
    6     Right,
    7 }
    8 
    9 impl Pos {
   10     fn calc_mult(pos_stack: &VecDeque<Pos>) -> u64 {
   11         pos_stack
   12             .iter()
   13             .map(|p| match p {
   14                 Self::Left => 3,
   15                 Self::Right => 2,
   16             })
   17             .product()
   18     }
   19 }
   20 
   21 #[derive(Debug, Clone, Copy)]
   22 struct Snailfish {
   23     value: u32,
   24     depth: i32,
   25     pos: Pos,
   26 }
   27 
   28 impl Snailfish {
   29     fn parse(s: &str) -> Vec<Snailfish> {
   30         let mut res = Vec::new();
   31         let mut prev_char = None;
   32         let mut curr_depth = 0;
   33         for c in s.chars() {
   34             match (prev_char, c.to_digit(10)) {
   35                 (Some('['), Some(v)) => res.push(Snailfish {
   36                     value: v,
   37                     depth: curr_depth,
   38                     pos: Pos::Left,
   39                 }),
   40                 (Some(','), Some(v)) => res.push(Snailfish {
   41                     value: v,
   42                     depth: curr_depth,
   43                     pos: Pos::Right,
   44                 }),
   45                 (_, None) => match c {
   46                     '[' => curr_depth += 1,
   47                     ']' => curr_depth -= 1,
   48                     _ => (),
   49                 },
   50                 _ => (),
   51             }
   52             prev_char = Some(c);
   53         }
   54         res
   55     }
   56 
   57     fn sum(a: &Vec<Snailfish>, b: &Vec<Snailfish>) -> Vec<Snailfish> {
   58         let mut sum = a
   59             .iter()
   60             .chain(b.iter())
   61             .map(|&v| v)
   62             .collect::<Vec<Snailfish>>();
   63         for v in sum.iter_mut() {
   64             v.depth += 1;
   65         }
   66         Self::reduce(sum)
   67     }
   68 
   69     fn reduce(mut val: Vec<Snailfish>) -> Vec<Snailfish> {
   70         loop {
   71             let mut new_val = Vec::<Snailfish>::new();
   72             let mut reduced = false;
   73             // explode
   74             let mut carry = 0;
   75             for mut v in val.into_iter() {
   76                 if !reduced && v.pos == Pos::Right && v.depth > 4 {
   77                     reduced = true;
   78                     let left = new_val.pop().unwrap();
   79                     let mut pair_pos = Pos::Left;
   80                     if let Some(last) = new_val.last_mut() {
   81                         last.value += left.value;
   82                         if last.pos == Pos::Left && v.depth - 1 == last.depth {
   83                             pair_pos = Pos::Right;
   84                         }
   85                     }
   86                     new_val.push(Snailfish {
   87                         value: 0,
   88                         depth: v.depth - 1,
   89                         pos: pair_pos,
   90                     });
   91                     carry = v.value;
   92                 } else {
   93                     v.value += carry;
   94                     carry = 0;
   95                     new_val.push(v);
   96                 }
   97             }
   98             val = new_val;
   99             if reduced {
  100                 continue;
  101             }
  102             // split
  103             // need to be a separate loop as first rule only triggers on Right elem
  104             let mut new_val = Vec::<Snailfish>::new();
  105             for v in val.into_iter() {
  106                 if !reduced && v.value >= 10 {
  107                     reduced = true;
  108                     new_val.push(Snailfish {
  109                         value: v.value / 2,
  110                         depth: v.depth + 1,
  111                         pos: Pos::Left,
  112                     });
  113                     new_val.push(Snailfish {
  114                         value: (v.value + 1) / 2,
  115                         depth: v.depth + 1,
  116                         pos: Pos::Right,
  117                     });
  118                 } else {
  119                     new_val.push(v);
  120                 }
  121             }
  122             val = new_val;
  123             if !reduced {
  124                 break;
  125             }
  126         }
  127         val
  128     }
  129 
  130     fn magnitude(val: &Vec<Snailfish>) -> u64 {
  131         let mut res = 0;
  132         let mut pos = std::collections::VecDeque::<Pos>::new();
  133         for v in val {
  134             while pos.len() < v.depth as usize {
  135                 pos.push_back(Pos::Left);
  136             }
  137             *pos.back_mut().unwrap() = v.pos;
  138             res += v.value as u64 * Pos::calc_mult(&pos);
  139             while let Some(&Pos::Right) = pos.back() {
  140                 pos.pop_back();
  141             }
  142             if let Some(back) = pos.back_mut() {
  143                 *back = Pos::Right;
  144             }
  145         }
  146         res
  147     }
  148 }
  149 
  150 fn main() {
  151     let input = std::fs::read_to_string("input.txt")
  152         .unwrap()
  153         .trim()
  154         .split('\n')
  155         .map(|s| Snailfish::parse(s))
  156         .collect::<Vec<Vec<_>>>();
  157     // 4207
  158     println!("Part 1: {}", part_1(&input));
  159     // 4635
  160     println!("Part 2: {}", part_2(&input));
  161 }
  162 
  163 fn part_1(input: &Vec<Vec<Snailfish>>) -> u64 {
  164     let sum = input
  165         .clone()
  166         .into_iter()
  167         .reduce(|a, b| Snailfish::sum(&a, &b))
  168         .unwrap();
  169     Snailfish::magnitude(&sum)
  170 }
  171 
  172 fn part_2(input: &Vec<Vec<Snailfish>>) -> u64 {
  173     let mut max_magnitude = 0;
  174     for a in input.iter() {
  175         for b in input.iter() {
  176             max_magnitude = max_magnitude.max(Snailfish::magnitude(&Snailfish::sum(a, b)));
  177         }
  178     }
  179 
  180     max_magnitude
  181 }