use super::PuzzleSolver;
use regex::Regex;
#[derive(Debug)]
pub struct Solver {
pub input: Vec<Command>,
}
impl PuzzleSolver for Solver {
fn part_one(&self) -> String {
println!("Multiplying final horizontal position by final depth");
let position = calculate_position(&self.input);
(position.horizontal * position.depth).to_string()
}
fn part_two(&self) -> String {
println!("Multiplying final horizontal position by final depth");
let position = calculate_position_v2(&self.input);
(position.horizontal * position.depth).to_string()
}
}
impl Solver {
pub fn new(input: &str) -> Solver {
let commands: Vec<Command>;
let re = Regex::new(r"^(forward|up|down) (\d+)$").expect("failed to compile regex");
commands = input
.trim()
.split('\n')
.into_iter()
.map(|x| parse_command(&re, x).unwrap())
.collect();
Solver { input: commands }
}
}
fn calculate_position(commands: &[Command]) -> Position {
let mut position = Position {
horizontal: 0,
depth: 0,
};
for command in commands.iter() {
match command {
Command::Forward(x) => position.horizontal += x,
Command::Up(x) => position.depth -= x,
Command::Down(x) => position.depth += x,
}
}
position
}
fn calculate_position_v2(commands: &[Command]) -> Position {
let mut aim: usize = 0;
let mut position = Position {
horizontal: 0,
depth: 0,
};
for command in commands.iter() {
match command {
Command::Forward(x) => {
position.horizontal += x;
position.depth += aim * x;
}
Command::Up(x) => aim -= x,
Command::Down(x) => aim += x,
}
}
position
}
fn parse_command(regex: &Regex, command: &str) -> Option<Command> {
let caps = regex.captures(command).expect("Not a valid command!");
let direction = caps.get(1)?.as_str();
let distance = caps.get(2)?.as_str();
let distance: usize = distance.parse().ok()?;
match direction {
"forward" => Some(Command::Forward(distance)),
"down" => Some(Command::Down(distance)),
"up" => Some(Command::Up(distance)),
_ => None,
}
}
#[derive(Debug, PartialEq)]
struct Position {
horizontal: usize,
depth: usize,
}
#[derive(Debug, PartialEq)]
pub enum Command {
Forward(usize),
Down(usize),
Up(usize),
}