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 by 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 => match input[index + 1] {
31                ESCAPE => 4,
32                _ => 2,
33            },
34            QUOTE => 3,
35            _ => 1,
36        };
37        result += skip - 1;
38        index += skip;
39    }
40
41    result
42}
43
44pub fn part2(input: &[u8]) -> u32 {
45    input
46        .iter()
47        .map(|&b| match b {
48            // Escape special characters.
49            QUOTE | SLASH => 1,
50            // Each line needs two enclosing quotes.
51            NEWLINE => 2,
52            _ => 0,
53        })
54        .sum()
55}