aoc/year2021/
day02.rs

1//! # Dive!
2//!
3//! Both part 1 and part 2 rely on the [`fold`] method. This method comes in useful for a lot
4//! of Advent of Code problems so is handy to know about. The input is parsed into a tuple enum
5//! [`Sub`] for convenience.
6//!
7//! [`fold`]: Iterator::fold
8use crate::util::iter::*;
9use crate::util::parse::*;
10
11#[derive(Clone, Copy)]
12pub enum Sub {
13    Up(i32),
14    Down(i32),
15    Forward(i32),
16}
17
18pub fn parse(input: &str) -> Vec<Sub> {
19    let helper = |[a, b]: [&str; 2]| {
20        let amount = b.signed();
21        match a {
22            "up" => Sub::Up(amount),
23            "down" => Sub::Down(amount),
24            "forward" => Sub::Forward(amount),
25            _ => unreachable!(),
26        }
27    };
28    input.split_ascii_whitespace().chunk::<2>().map(helper).collect()
29}
30
31pub fn part1(input: &[Sub]) -> i32 {
32    let helper = |(position, depth), next| match next {
33        Sub::Up(n) => (position, depth - n),
34        Sub::Down(n) => (position, depth + n),
35        Sub::Forward(n) => (position + n, depth),
36    };
37    let (position, depth) = input.iter().copied().fold((0, 0), helper);
38    position * depth
39}
40
41pub fn part2(input: &[Sub]) -> i32 {
42    let helper = |(position, depth, aim), next| match next {
43        Sub::Up(n) => (position, depth, aim - n),
44        Sub::Down(n) => (position, depth, aim + n),
45        Sub::Forward(n) => (position + n, depth + aim * n, aim),
46    };
47    let (position, depth, _) = input.iter().copied().fold((0, 0, 0), helper);
48    position * depth
49}