aboutsummaryrefslogtreecommitdiff
path: root/2022/13/common.rs
blob: f49f3bccfc1396ae76b0bd50aa9e8cb4d2496c6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use std::cmp::Ordering;

#[derive(Debug)]
pub enum Packet {
    Number(i64),
    List(Vec<Packet>)
}

fn compare_lists(l: &Vec<Packet>, k: &Vec<Packet>) -> Ordering {
    for i in 0..std::cmp::min(l.len(), k.len()) {
        let ord = compare(&l[i], &k[i]);
        if ord != Ordering::Equal { return ord; }
    }
    l.len().cmp(&k.len())
}

fn compare_list_single(l: &Vec<Packet>, p: &Packet) -> Ordering {
    if l.len() == 0 { return Ordering::Less; }
    let ord = compare(&l[0], p);
    if ord != Ordering::Equal { return ord; }
    l.len().cmp(&1)
}

pub fn compare(p: &Packet, q: &Packet) -> Ordering {
    match p {
        Packet::Number(n) => {
            match q {
                Packet::Number(m) => n.cmp(&m),
                Packet::List(k) => compare_list_single(k, p).reverse()
            } 
        },
        Packet::List(l) => {
            match q {
                Packet::Number(_) => compare_list_single(l, q),
                Packet::List(k) => compare_lists(l, k)
            }
        }
    }
}

fn parse_int(line: &[u8], i: &mut usize) -> i64 {
    let mut r: i64 = 0;
    loop {
        match line[*i] {
            b'0'..=b'9' => r = r * 10 + (line[*i] as i64) - ('0' as i64),
            b',' | b']' => return r,
            x => panic!("Error: unexpected '{}' at position {} in parse_int",
                        x as char, *i)
        }
        *i += 1;
    }
}

fn parse_list(line: &[u8], i: &mut usize) -> Packet {
    if line[*i] != b'[' {
        panic!("Error: sub-list at {} does not start with '['", *i);
    }
    *i += 1;
    let mut v = Vec::<Packet>::new();
    while *i < line.len() && line[*i] != b'\n' {
        match line[*i] {
            b']' => { *i += 1; return Packet::List(v); },
            b'[' => v.push(parse_list(line, i)),
            b'0'..=b'9' => v.push(Packet::Number(parse_int(line, i))),
            b' ' | b',' => *i += 1,
            x => panic!("Error: unexpected '{}' at position {}", x as char, *i)
        }
    }
    panic!("Error: finished parsing at {}, but ']' not found", *i);
}

pub fn parse(line: &[u8]) -> Packet {
    let mut i = 0;
    parse_list(line, &mut i)
}

Generated with cgit - Back to sebastiano.tronto.net