aoc/year2016/
day09.rs

1//! # Explosives in Cyberspace
2//!
3//! The only difference between part one and two is that we recursively decompress inner sequences.
4use crate::util::parse::*;
5
6pub fn parse(input: &str) -> &[u8] {
7    input.trim().as_bytes()
8}
9
10pub fn part1(input: &[u8]) -> usize {
11    decompress(input, false)
12}
13
14pub fn part2(input: &[u8]) -> usize {
15    decompress(input, true)
16}
17
18fn decompress(mut slice: &[u8], recurse: bool) -> usize {
19    let mut length = 0;
20
21    while !slice.is_empty() {
22        if slice[0] == b'(' {
23            let (next, amount) = number(slice);
24            let (next, repeat) = number(next);
25
26            let start = 1;
27            let end = start + amount;
28            let result = if recurse { decompress(&next[start..end], true) } else { amount };
29
30            slice = &next[end..];
31            length += result * repeat;
32        } else {
33            slice = &slice[1..];
34            length += 1;
35        }
36    }
37
38    length
39}
40
41fn number(slice: &[u8]) -> (&[u8], usize) {
42    // Parse number digit by digit, skipping over the delimeter at the start but leaving the
43    // delimeter at the end.
44    let mut index = 2;
45    let mut acc = slice[1].to_decimal() as usize;
46
47    while slice[index].is_ascii_digit() {
48        acc = 10 * acc + slice[index].to_decimal() as usize;
49        index += 1;
50    }
51
52    (&slice[index..], acc)
53}