advent-of-code

Perserverance, or the lack thereof

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

main.rs (4495B)

    1 use std::cmp::Ordering;
    2 use std::collections::VecDeque;
    3 
    4 #[derive(PartialEq, Eq, Clone, Debug)]
    5 enum Packet {
    6     List(Vec<Packet>),
    7     Number(i32),
    8 }
    9 
   10 #[derive(Clone, Debug)]
   11 enum Chunk {
   12     ListStart,
   13     Number(i32),
   14     Packet(Packet),
   15 }
   16 
   17 impl Packet {
   18     fn from_str(s: &str) -> Option<Packet> {
   19         let mut chunks = VecDeque::new();
   20         let mut buf = String::new();
   21         for ch in s.chars() {
   22             match ch {
   23                 '[' => chunks.push_back(Chunk::ListStart),
   24                 ']' => {
   25                     if !buf.is_empty() {
   26                         chunks.push_back(Chunk::Number(buf.parse::<i32>().unwrap()));
   27                         buf.clear();
   28                     }
   29                     let mut new_list = Vec::new();
   30                     while let Some(c) = chunks.pop_back() {
   31                         match c {
   32                             Chunk::ListStart => {
   33                                 chunks.push_back(Chunk::Packet(Packet::List(new_list)));
   34                                 break;
   35                             }
   36                             Chunk::Number(x) => {
   37                                 new_list.insert(0, Packet::Number(x));
   38                             }
   39                             Chunk::Packet(c) => {
   40                                 new_list.insert(0, c);
   41                             }
   42                         }
   43                     }
   44                 }
   45                 ',' => {
   46                     if !buf.is_empty() {
   47                         chunks.push_back(Chunk::Number(buf.parse::<i32>().unwrap()));
   48                         buf.clear();
   49                     }
   50                     buf.clear();
   51                 }
   52                 ch => buf.push(ch),
   53             }
   54         }
   55         if let Some(c) = chunks.into_iter().nth(0) {
   56             match c {
   57                 Chunk::Packet(cc) => Some(cc),
   58                 _ => None,
   59             }
   60         } else {
   61             None
   62         }
   63     }
   64 }
   65 
   66 impl Ord for Packet {
   67     fn cmp(&self, other: &Self) -> Ordering {
   68         match (self, other) {
   69             (Self::Number(a), Self::Number(b)) => a.cmp(b),
   70             (Self::Number(a), Self::List(_)) => Packet::List(vec![Packet::Number(*a)]).cmp(other),
   71             (Self::List(_), Self::Number(b)) => self.cmp(&Packet::List(vec![Packet::Number(*b)])),
   72             (Self::List(a), Self::List(b)) => {
   73                 let mut aa = a.iter();
   74                 let mut bb = b.iter();
   75                 loop {
   76                     match (aa.next(), bb.next()) {
   77                         (Some(aaa), Some(bbb)) => match aaa.cmp(bbb) {
   78                             Ordering::Less => break Ordering::Less,
   79                             Ordering::Equal => (),
   80                             Ordering::Greater => break Ordering::Greater,
   81                         },
   82                         (Some(_), None) => {
   83                             break Ordering::Greater;
   84                         }
   85                         (None, Some(_)) => {
   86                             break Ordering::Less;
   87                         }
   88                         (None, None) => {
   89                             break Ordering::Equal;
   90                         }
   91                     }
   92                 }
   93             }
   94         }
   95     }
   96 }
   97 
   98 impl PartialOrd for Packet {
   99     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  100         Some(self.cmp(other))
  101     }
  102 }
  103 
  104 fn main() {
  105     let input = std::fs::read_to_string("input.txt")
  106         .unwrap()
  107         .trim()
  108         .split("\n\n")
  109         .map(|p| {
  110             p.split('\n')
  111                 .map(|s| Packet::from_str(s).unwrap())
  112                 .collect()
  113         })
  114         .collect::<Vec<Vec<Packet>>>();
  115     // 6478
  116     println!("Part 1: {}", part_1(&input));
  117     // 21922
  118     println!("Part 2: {}", part_2(&input));
  119 }
  120 
  121 fn part_1(input: &Vec<Vec<Packet>>) -> usize {
  122     let mut tot = 0;
  123     for (i, pp) in input.iter().enumerate() {
  124         if let Ordering::Less = pp[0].cmp(&pp[1]) {
  125             tot += i + 1;
  126         }
  127     }
  128     tot
  129 }
  130 
  131 fn part_2(input: &Vec<Vec<Packet>>) -> usize {
  132     let divider_1 = Packet::List(vec![Packet::Number(2)]);
  133     let divider_2 = Packet::List(vec![Packet::Number(6)]);
  134     let mut all_packet = {
  135         let mut tmp = vec![divider_1.clone(), divider_2.clone()];
  136         for pp in input {
  137             tmp.append(&mut pp.clone());
  138         }
  139         tmp
  140     };
  141     all_packet.sort();
  142     (all_packet.binary_search(&divider_1).unwrap() + 1)
  143         * (all_packet.binary_search(&divider_2).unwrap() + 1)
  144 }