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
//! # Explosives in Cyberspace
//!
//! The only difference between part one and two is that we recursively decompress inner sequences.
use crate::util::parse::*;

pub fn parse(input: &str) -> &[u8] {
    input.trim().as_bytes()
}

pub fn part1(input: &[u8]) -> usize {
    decompress(input, false)
}

pub fn part2(input: &[u8]) -> usize {
    decompress(input, true)
}

fn decompress(mut slice: &[u8], recurse: bool) -> usize {
    let mut length = 0;

    while !slice.is_empty() {
        if slice[0] == b'(' {
            let (next, amount) = number(slice);
            let (next, repeat) = number(next);

            let start = 1;
            let end = start + amount;
            let result = if recurse { decompress(&next[start..end], true) } else { amount };

            slice = &next[end..];
            length += result * repeat;
        } else {
            slice = &slice[1..];
            length += 1;
        }
    }

    length
}

fn number(slice: &[u8]) -> (&[u8], usize) {
    // Parse number digit by digit, skipping over the delimeter at the start but leaving the
    // delimeter at the end.
    let mut index = 2;
    let mut acc = slice[1].to_decimal() as usize;

    while slice[index].is_ascii_digit() {
        acc = 10 * acc + slice[index].to_decimal() as usize;
        index += 1;
    }

    (&slice[index..], acc)
}