summaryrefslogtreecommitdiff
path: root/2018/src/day5.rs
blob: 4638858f0795230f2fcb66c0a3b4c9b66a29b628 (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
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::io;
use std::io::BufRead;

fn reactive(a: u8, b: u8) -> bool {
    a == b + 32 || b == a + 32
}

fn react(line: &mut [u8]) -> usize {
    let len = line.len() as i64;
    let mut gone = vec![false; len as usize];

    let mut top: i64 = 0;
    for ptr in 1..len {
        if top >= ptr {
            continue;
        } else if reactive(line[top as usize], line[ptr as usize]) {
            gone[top as usize] = true;
            gone[ptr as usize] = true;
            top -= 1;
            while top > 0 && gone[top as usize] {
                top -= 1;
            }
            if top < 0 {
                top = ptr + 1;
            }
        } else {
            top = ptr;
        }
    }

    let mut j = 0;
    for i in 0..len as usize {
        if !gone[i] {
            if j < i { line[j] = line[i]; }
            j += 1;
        }
    }

    j
}

fn full_react(bytes: &mut Vec<u8>, mut len: usize) -> usize {
    loop {
        let newlen = react(&mut bytes[..len]);
        if newlen == len { break; }
        len = newlen;
    }

    len
}

// Pass 'typ' as uppercase.
fn remove_type(dest: &mut [u8], src: &[u8], typ: u8) -> usize {
    let mut j = 0;
    for i in 0..src.len() {
        if src[i] != typ && src[i] != typ + 32 {
            dest[j] = src[i];
            j += 1;
        }
    }

    j
}

pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {
    let line = reader.lines().next().unwrap().unwrap();
    let mut bytes: Vec<u8> = line.bytes().collect();
    let mut len = bytes.len();

    len = full_react(&mut bytes, len);

    let part1 = len;

    let mut minlen = len;

    let mut bytes2 = bytes[..len].to_vec();
    for typ in 65..65+26 {
        let newlen = remove_type(&mut bytes2, &bytes[..len], typ);
        let len2 = full_react(&mut bytes2, newlen);
        if len2 < minlen {
            minlen = len2;
        }
    }

    let part2 = minlen;

    Ok((part1.to_string(), part2.to_string()))
}