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 stream of raw
5//! ASCII `u8` bytes including newlines.
6//!
7//! For part one we run a small state machine using [`fold`] to keep track of the current and
8//! previous characters. If we encounter a hexadecimal escape then four characters become one so the
9//! difference increases by three. The sequences `\\` and `\"` both increase the difference by one.
10//! Each newline increases the difference by two since every line is enclosed with two quotes.
11//!
12//! Part two is even more straightforward with no need for statekeeping. Quotes and backslashes
13//! need to be escaped so increase the difference by one. As before each newline increases by the
14//! difference by two.
15//!
16//! [`fold`]: Iterator::fold
17const NEWLINE: u8 = 10;
18const QUOTE: u8 = 34;
19const SLASH: u8 = 92;
20const ESCAPE: u8 = 120;
21
22pub fn parse(input: &str) -> &str {
23 input
24}
25
26pub fn part1(input: &str) -> u32 {
27 let (_, result) = input.bytes().fold((false, 0), |(flag, count), b| match (flag, b) {
28 (true, ESCAPE) => (false, count + 3),
29 (true, _) => (false, count + 1),
30 (false, SLASH) => (true, count),
31 (false, NEWLINE) => (false, count + 2),
32 _ => (false, count),
33 });
34 result
35}
36
37pub fn part2(input: &str) -> u32 {
38 input
39 .bytes()
40 .map(|b| match b {
41 QUOTE | SLASH => 1,
42 NEWLINE => 2,
43 _ => 0,
44 })
45 .sum()
46}