1
Fork 0
advent-of-code/source/year_2020/day_12/mod.rs

94 lines
2.6 KiB
Rust

use crate::prelude::*;
mod extra;
use extra::*;
pub fn solution() -> Solution {
Solution::new(Day::new(12, 2020), part_1, part_2).with_expected(1496, 63843)
}
fn parse_instructions(input: &str) -> Vec<Instruction> {
input.lines().map(Into::into).collect()
}
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())
}
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())
}