aoc

My solutions for the Advent of Code
git clone https://git.tronto.net/aoc
Download | Log | Files | Refs | README

common.rs (2149B)


      1 use std::cmp::Ordering;
      2 
      3 #[derive(Debug)]
      4 pub enum Packet {
      5     Number(i64),
      6     List(Vec<Packet>)
      7 }
      8 
      9 fn compare_lists(l: &Vec<Packet>, k: &Vec<Packet>) -> Ordering {
     10     for i in 0..std::cmp::min(l.len(), k.len()) {
     11         let ord = compare(&l[i], &k[i]);
     12         if ord != Ordering::Equal { return ord; }
     13     }
     14     l.len().cmp(&k.len())
     15 }
     16 
     17 fn compare_list_single(l: &Vec<Packet>, p: &Packet) -> Ordering {
     18     if l.len() == 0 { return Ordering::Less; }
     19     let ord = compare(&l[0], p);
     20     if ord != Ordering::Equal { return ord; }
     21     l.len().cmp(&1)
     22 }
     23 
     24 pub fn compare(p: &Packet, q: &Packet) -> Ordering {
     25     match p {
     26         Packet::Number(n) => {
     27             match q {
     28                 Packet::Number(m) => n.cmp(&m),
     29                 Packet::List(k) => compare_list_single(k, p).reverse()
     30             } 
     31         },
     32         Packet::List(l) => {
     33             match q {
     34                 Packet::Number(_) => compare_list_single(l, q),
     35                 Packet::List(k) => compare_lists(l, k)
     36             }
     37         }
     38     }
     39 }
     40 
     41 fn parse_int(line: &[u8], i: &mut usize) -> i64 {
     42     let mut r: i64 = 0;
     43     loop {
     44         match line[*i] {
     45             b'0'..=b'9' => r = r * 10 + (line[*i] as i64) - ('0' as i64),
     46             b',' | b']' => return r,
     47             x => panic!("Error: unexpected '{}' at position {} in parse_int",
     48                         x as char, *i)
     49         }
     50         *i += 1;
     51     }
     52 }
     53 
     54 fn parse_list(line: &[u8], i: &mut usize) -> Packet {
     55     if line[*i] != b'[' {
     56         panic!("Error: sub-list at {} does not start with '['", *i);
     57     }
     58     *i += 1;
     59     let mut v = Vec::<Packet>::new();
     60     while *i < line.len() && line[*i] != b'\n' {
     61         match line[*i] {
     62             b']' => { *i += 1; return Packet::List(v); },
     63             b'[' => v.push(parse_list(line, i)),
     64             b'0'..=b'9' => v.push(Packet::Number(parse_int(line, i))),
     65             b' ' | b',' => *i += 1,
     66             x => panic!("Error: unexpected '{}' at position {}", x as char, *i)
     67         }
     68     }
     69     panic!("Error: finished parsing at {}, but ']' not found", *i);
     70 }
     71 
     72 pub fn parse(line: &[u8]) -> Packet {
     73     let mut i = 0;
     74     parse_list(line, &mut i)
     75 }