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    input
20        .split_ascii_whitespace()
21        .chunk::<2>()
22        .map(|[first, second]| {
23            let amount = second.signed();
24            match first {
25                "up" => Sub::Up(amount),
26                "down" => Sub::Down(amount),
27                "forward" => Sub::Forward(amount),
28                _ => unreachable!(),
29            }
30        })
31        .collect()
32}
33
34pub fn part1(input: &[Sub]) -> i32 {
35    let (position, depth) =
36        input.iter().copied().fold((0, 0), |(position, depth), next| match next {
37            Sub::Up(n) => (position, depth - n),
38            Sub::Down(n) => (position, depth + n),
39            Sub::Forward(n) => (position + n, depth),
40        });
41    position * depth
42}
43
44pub fn part2(input: &[Sub]) -> i32 {
45    let (position, depth, _) =
46        input.iter().copied().fold((0, 0, 0), |(position, depth, aim), next| match next {
47            Sub::Up(n) => (position, depth, aim - n),
48            Sub::Down(n) => (position, depth, aim + n),
49            Sub::Forward(n) => (position + n, depth + aim * n, aim),
50        });
51    position * depth
52}