100 lines
2.8 KiB
Rust
100 lines
2.8 KiB
Rust
//! Day 12 of 2020.
|
|
|
|
use crate::prelude::*;
|
|
|
|
mod extra;
|
|
|
|
use extra::*;
|
|
|
|
/// Get the solution for day 12 of 2020.
|
|
pub fn solution() -> Solution {
|
|
Solution::new(Day::new(12, 2020), part_1, part_2).with_expected(1496, 63843)
|
|
}
|
|
|
|
/// Parse the list of [`Instruction`]s based on the puzzle input.
|
|
fn parse_instructions(input: &str) -> Vec<Instruction> {
|
|
input.lines().map(Into::into).collect()
|
|
}
|
|
|
|
/// The logic to solve part one.
|
|
fn part_1(input: &str) -> Result<String> {
|
|
let instructions = parse_instructions(input);
|
|
let mut horizontal = 0;
|
|
let mut vertical = 0;
|
|
let mut direction: i32 = 90;
|
|
|
|
for instruction in instructions {
|
|
match instruction.action {
|
|
Action::Forward => {
|
|
match direction {
|
|
90 => horizontal += instruction.value,
|
|
270 => horizontal -= instruction.value,
|
|
180 => vertical += instruction.value,
|
|
0 => vertical -= instruction.value,
|
|
_ => unreachable!("{direction}"),
|
|
};
|
|
}
|
|
Action::Left => direction -= instruction.value,
|
|
Action::Right => direction += instruction.value,
|
|
Action::East => horizontal += instruction.value,
|
|
Action::West => horizontal -= instruction.value,
|
|
Action::South => vertical += instruction.value,
|
|
Action::North => vertical -= instruction.value,
|
|
};
|
|
|
|
direction = match direction % 360 {
|
|
-270 => 90,
|
|
-90 => 270,
|
|
0 => 0,
|
|
value => value.abs(),
|
|
};
|
|
}
|
|
|
|
Ok((horizontal.abs() + vertical.abs()).to_string())
|
|
}
|
|
|
|
/// The logic to solve part two.
|
|
fn part_2(input: &str) -> Result<String> {
|
|
let instructions = parse_instructions(input);
|
|
|
|
let mut horizontal = 0;
|
|
let mut vertical = 0;
|
|
|
|
let mut wp_horizontal = 10;
|
|
let mut wp_vertical = -1;
|
|
|
|
for instruction in instructions {
|
|
match instruction.action {
|
|
Action::Forward => {
|
|
horizontal += wp_horizontal * instruction.value;
|
|
vertical += wp_vertical * instruction.value;
|
|
}
|
|
Action::East => wp_horizontal += instruction.value,
|
|
Action::West => wp_horizontal -= instruction.value,
|
|
Action::South => wp_vertical += instruction.value,
|
|
Action::North => wp_vertical -= instruction.value,
|
|
_ => (),
|
|
};
|
|
|
|
match (&instruction.action, instruction.value) {
|
|
(Action::Left, 90) | (Action::Right, 270) => {
|
|
let intermediate_vertical = wp_vertical;
|
|
wp_vertical = -wp_horizontal;
|
|
wp_horizontal = intermediate_vertical;
|
|
}
|
|
(Action::Left, 180) | (Action::Right, 180) => {
|
|
wp_horizontal = -wp_horizontal;
|
|
wp_vertical = -wp_vertical;
|
|
}
|
|
(Action::Left, 270) | (Action::Right, 90) => {
|
|
let intermediate_horizontal = wp_horizontal;
|
|
wp_horizontal = -wp_vertical;
|
|
wp_vertical = intermediate_horizontal;
|
|
}
|
|
_ => (),
|
|
};
|
|
}
|
|
|
|
Ok((horizontal.abs() + vertical.abs()).to_string())
|
|
}
|