Skip to main content

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.
4pub fn parse(input: &str) -> &[u8] {
5    input.trim().as_bytes()
6}
7
8pub fn part1(input: &[u8]) -> usize {
9    decompress(input, false)
10}
11
12pub fn part2(input: &[u8]) -> usize {
13    decompress(input, true)
14}
15
16fn decompress(mut slice: &[u8], part_two: bool) -> usize {
17    let mut length = 0;
18
19    // Find the next marker.
20    while let Some(start) = slice.iter().position(|&b| b == b'(') {
21        let (next, amount) = number(&slice[start + 1..]);
22        let (next, repeat) = number(next);
23
24        // For part two, recursively decompress data.
25        let result = if part_two { decompress(&next[..amount], true) } else { amount };
26
27        slice = &next[amount..];
28        length += start + result * repeat;
29    }
30
31    // Add remaining plain data that doesn't contain any marker.
32    length + slice.len()
33}
34
35fn number(slice: &[u8]) -> (&[u8], usize) {
36    let end = slice.iter().position(|b| !b.is_ascii_digit()).unwrap();
37    let n = slice[..end].iter().fold(0, |n, &b| 10 * n + (b - b'0') as usize);
38    // Skip over trailing delimiter.
39    (&slice[end + 1..], n)
40}