use std::str::FromStr; use color_eyre::{ eyre::{eyre, Error}, Result, }; pub fn solve() -> Result<()> { let input_data = include_str!("../../data/day_02.txt").trim(); println!("Day 02 Part 1: {}", part_1(input_data)?); println!("Day 02 Part 2: {}", part_2(input_data)?); Ok(()) } #[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(eyre!("Command not found in line: {}", s))?; let amount = split .next() .ok_or(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()) } 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()) }