use crate::prelude::*; pub fn solution() -> Solution { Solution::new(Day::new(2, 2021), part_1, part_2) .with_expected(1727835, 1544000595) } #[derive(Debug)] enum Command { Forward(i32), Down(i32), 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)), } } } #[derive(Debug, Default)] struct Submarine { aim: i32, depth: i32, horizontal_position: i32, } impl Submarine { 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, } } 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, } } fn final_result(&self) -> i32 { self.horizontal_position * self.depth } } fn parse_commands(input: &str) -> Result> { input.lines().map(Command::from_str).collect::>() } 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()) } 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()) }