From c88b97182d19b6d191d706a9cc1c0112646ab744 Mon Sep 17 00:00:00 2001 From: Andrew Glaze Date: Thu, 28 Dec 2023 15:43:02 -0500 Subject: [PATCH] day12 --- src/day12.rs | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 138 insertions(+) create mode 100644 src/day12.rs diff --git a/src/day12.rs b/src/day12.rs new file mode 100644 index 0000000..592b428 --- /dev/null +++ b/src/day12.rs @@ -0,0 +1,137 @@ +use aoc_runner_derive::{aoc, aoc_generator}; + +use Instruction::*; +use itertools::Itertools; + +#[derive(Debug)] +enum Instruction { + MoveNorth(i32), + MoveSouth(i32), + MoveEast(i32), + MoveWest(i32), + TurnLeft(i32), + TurnRight(i32), + MoveForward(i32) +} + +impl From<(char, i32)> for Instruction { + fn from(value: (char, i32)) -> Self { + match value { + (i, v) if i == 'N' => MoveNorth(v), + (i, v) if i == 'S' => MoveSouth(v), + (i, v) if i == 'E' => MoveEast(v), + (i, v) if i == 'W' => MoveWest(v), + (i, v) if i == 'L' => TurnLeft(v), + (i, v) if i == 'R' => TurnRight(v), + (i, v) if i == 'F' => MoveForward(v), + _ => unreachable!() + } + } +} + +#[aoc_generator(day12)] +fn parse(input: &str) -> Vec { + input + .lines() + .map(|line| { + (line.chars().next().unwrap(), line[1..].parse::().unwrap()).into() + }) + .collect_vec() +} + +const DIR_POS_MODIFIER: [(i32, i32); 4] = [(1, 0), (0, -1), (-1, 0), (0, 1)]; + +#[aoc(day12, part1)] +fn part1(input: &Vec) -> i32 { + let mut x = 0; + let mut y = 0; + let mut direction = 0; // 0 is east, thus 90 is south, 180 is west, and 270 is north + + for instr in input { + match instr { + MoveNorth(val) => y += val, + MoveSouth(val) => y -= val, + MoveEast(val) => x += val, + MoveWest(val) => x -= val, + TurnLeft(val) => { + direction -= val; + if direction < 0 { + direction += 360; + } + }, + TurnRight(val) => { + direction += val; + if direction >= 360 { + direction -= 360 + } + }, + MoveForward(val) => { + let (xmod, ymod) = DIR_POS_MODIFIER[(direction / 90) as usize]; + x += xmod * val; + y += ymod * val; + }, + } + } + + x.abs() + y.abs() +} + +#[aoc(day12, part2)] +fn part2(input: &Vec) -> i32 { + let mut way_x = 10; + let mut way_y = 1; + + let mut ship_x: i32 = 0; + let mut ship_y: i32 = 0; + + for instr in input { + match instr { + MoveNorth(val) => way_y += val, + MoveSouth(val) => way_y -= val, + MoveEast(val) => way_x += val, + MoveWest(val) => way_x -= val, + TurnLeft(val) => { + for _ in 0..(val / 90) { + let tmp = way_y; + way_y = way_x; + way_x = -tmp; + } + }, + TurnRight(val) => { + for _ in 0..(val / 90) { + let tmp = way_y; + way_y = -way_x; + way_x = tmp; + } + }, + MoveForward(val) => { + ship_x += way_x * val; + ship_y += way_y * val; + }, + } + } + + ship_x.abs() + ship_y.abs() +} + + +#[cfg(test)] +mod tests { + use super::*; + +const EX: &str = r"F10 +N3 +F7 +R90 +F11"; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EX)), 25); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse(EX)), 286); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 78c4048..e1e8654 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day12; mod day10; mod day9; mod day8;