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], part_two: bool) -> usize {
19    let mut length = 0;
20
21    // Find the next marker.
22    while let Some(start) = slice.iter().position(|&b| b == b'(') {
23        let (next, amount) = number(&slice[start + 1..]);
24        let (next, repeat) = number(next);
25
26        // For part two, recursively decompress data.
27        let result = if part_two { decompress(&next[..amount], true) } else { amount };
28
29        slice = &next[amount..];
30        length += start + result * repeat;
31    }
32
33    // Add remaining plain data that doesn't container any marker.
34    length + slice.len()
35}
36
37fn number(slice: &[u8]) -> (&[u8], usize) {
38    // Parse number digit by digit.
39    let mut index = 0;
40    let mut acc = 0;
41
42    while slice[index].is_ascii_digit() {
43        acc = 10 * acc + slice[index].to_decimal() as usize;
44        index += 1;
45    }
46
47    // Skip over trailing delimeter.
48    (&slice[index + 1..], acc)
49}