//! Day 02 of 2021. use crate::prelude::*; /// Get the solution for day 02 of 2021. pub fn solution() -> Solution { Solution::new(Day::new(2, 2021), part_1, part_2) .with_expected(1727835, 1544000595) } /// The possible commands to execute. #[derive(Debug)] enum Command { /// Move forward a given amount. Forward(i32), /// Move down a given amount. Down(i32), /// Move up a given amount. Up(i32), } impl FromStr for Command { type Err = Error; fn from_str(s: &str) -> Result { let mut split = s.split(' '); let command = split .next() .ok_or_else(|| eyre!("Command not found in line: {}", s))?; let amount = split .next() .ok_or_else(|| eyre!("Amount not found in line: {}", s))? .parse()?; match command { "forward" => Ok(Self::Forward(amount)), "down" => Ok(Self::Down(amount)), "up" => Ok(Self::Up(amount)), _ => Err(eyre!("Unknown command: {}", s)), } } } /// The submarine data. #[derive(Debug, Default)] struct Submarine { /// The direction the submarine is aiming at. aim: i32, /// The depth of the submarine is at. depth: i32, /// The horizontal position of the submarine. horizontal_position: i32, } impl Submarine { /// Execute the [`Command`] according to the logic for part one. fn execute_command_1(&mut self, command: Command) { match command { Command::Forward(amount) => self.horizontal_position += amount, Command::Down(amount) => self.depth += amount, Command::Up(amount) => self.depth -= amount, } } /// Execute the [`Command`] according to the logic for part two. fn execute_command_2(&mut self, command: Command) { match command { Command::Forward(amount) => { self.horizontal_position += amount; self.depth += self.aim * amount; } Command::Down(amount) => self.aim += amount, Command::Up(amount) => self.aim -= amount, } } /// Calculate the final result. fn final_result(&self) -> i32 { self.horizontal_position * self.depth } } /// Parse the list of [`Command`]s from the puzzle input. fn parse_commands(input: &str) -> Result> { input.lines().map(Command::from_str).collect::>() } /// The logic to solve part one. fn part_1(input: &str) -> Result { let mut submarine = Submarine::default(); parse_commands(input)? .into_iter() .for_each(|command| submarine.execute_command_1(command)); Ok(submarine.final_result().to_string()) } /// The logic to solve part two. fn part_2(input: &str) -> Result { let mut submarine = Submarine::default(); parse_commands(input)? .into_iter() .for_each(|command| submarine.execute_command_2(command)); Ok(submarine.final_result().to_string()) }