109 lines
2.7 KiB
Rust
109 lines
2.7 KiB
Rust
//! 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<Self, Self::Err> {
|
|
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<Vec<Command>> {
|
|
input.lines().map(Command::from_str).collect::<Result<_>>()
|
|
}
|
|
|
|
/// The logic to solve part one.
|
|
fn part_1(input: &str) -> Result<String> {
|
|
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<String> {
|
|
let mut submarine = Submarine::default();
|
|
|
|
parse_commands(input)?
|
|
.into_iter()
|
|
.for_each(|command| submarine.execute_command_2(command));
|
|
|
|
Ok(submarine.final_result().to_string())
|
|
}
|