//! 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 { input.lines().map(Into::into).collect() } /// The logic to solve part one. fn part_1(input: &str) -> Result { 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 { 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()) }