Skip to main content

aoc/year2015/
day08.rs

1//! # Matchsticks
2//!
3//! While [regular expressions](https://en.wikipedia.org/wiki/Regular_expression) may feel like a
4//! natural choice, it's much faster and easier to simply treat the input as a single stream of raw
5//! ASCII `u8` bytes without splitting line by line.
6//!
7//! For part one we skip over the first quote of each line. The last quote on each line increases
8//! the difference by two since every line is enclosed with two quotes. If we encounter a
9//! hexadecimal escape then four characters become one so the difference increases by three.
10//! The sequences `\\` and `\"` both increase the difference by one.
11//!
12//! Part two is even more straightforward. Quotes and backslashes need to be escaped so increase
13//! the difference by one. Each newline increases the difference by two.
14const NEWLINE: u8 = b'\n';
15const QUOTE: u8 = b'\"';
16const SLASH: u8 = b'\\';
17const ESCAPE: u8 = b'x';
18
19pub fn parse(input: &str) -> &[u8] {
20    input.as_bytes()
21}
22
23pub fn part1(input: &[u8]) -> usize {
24    // Skip very first quote to prevent double counting.
25    let mut index = 1;
26    let mut result = 0;
27
28    while index < input.len() {
29        let skip = match input[index] {
30            SLASH if input[index + 1] == ESCAPE => 4,
31            SLASH => 2,
32            QUOTE => 3,
33            _ => 1,
34        };
35        result += skip - 1;
36        index += skip;
37    }
38
39    result
40}
41
42pub fn part2(input: &[u8]) -> u32 {
43    input
44        .iter()
45        .map(|&b| match b {
46            // Escape special characters.
47            QUOTE | SLASH => 1,
48            // Each line needs two enclosing quotes.
49            NEWLINE => 2,
50            _ => 0,
51        })
52        .sum()
53}