diff --git a/input/2020/day12.txt b/input/2020/day12.txt new file mode 100644 index 0000000..2e915fa --- /dev/null +++ b/input/2020/day12.txt @@ -0,0 +1,786 @@ +S2 +W5 +F20 +E3 +S5 +R90 +W5 +F48 +R180 +E3 +S3 +E5 +S3 +F83 +S1 +W5 +F81 +W3 +R90 +F88 +S2 +R90 +E2 +L90 +W4 +F77 +E1 +R90 +S4 +E2 +F89 +N2 +L90 +N2 +N2 +E3 +L180 +N1 +F82 +R90 +S3 +F64 +W1 +R180 +S2 +R180 +F28 +L180 +S3 +F100 +E1 +S4 +S5 +R90 +F3 +W5 +N4 +F9 +N5 +E4 +R90 +F83 +L180 +W3 +N5 +W2 +R180 +W1 +S4 +L90 +S5 +R90 +R90 +F36 +L180 +W1 +F88 +E3 +R90 +F13 +W1 +F13 +W4 +R90 +E3 +F98 +S4 +E5 +R90 +F77 +E5 +L180 +N5 +R90 +E1 +F70 +L180 +F54 +E5 +F9 +L180 +N3 +F77 +E2 +F81 +E2 +S1 +F41 +L90 +F32 +S3 +F66 +N2 +E4 +R90 +F80 +R90 +W1 +R90 +S3 +F65 +S4 +R90 +W4 +S4 +R90 +W4 +S2 +E1 +F44 +R90 +F53 +E3 +F67 +S5 +L90 +R90 +W2 +S2 +E3 +N5 +F97 +N3 +E1 +R90 +W4 +N5 +S4 +F38 +N5 +N1 +W4 +S3 +E1 +S3 +F87 +E1 +R90 +E2 +L180 +S1 +L90 +F29 +R90 +S2 +F95 +N2 +E5 +F24 +W1 +F71 +E3 +L90 +F16 +L90 +S5 +L90 +W1 +F95 +L90 +W2 +F97 +E4 +R90 +N5 +F77 +E2 +L90 +F71 +L90 +W2 +R90 +F75 +E1 +S1 +F28 +F86 +R90 +E3 +F9 +N2 +W4 +S1 +L90 +F10 +W4 +L90 +S5 +E1 +L90 +W2 +S3 +F41 +L90 +S5 +F73 +L90 +S4 +F80 +W4 +R180 +S4 +E3 +F89 +E5 +N5 +L90 +F66 +N4 +W1 +F93 +W1 +F27 +F68 +N4 +F23 +L90 +F14 +S3 +F74 +N2 +E2 +R90 +S4 +F85 +N2 +L180 +L180 +F55 +S5 +E5 +F42 +N2 +R90 +F53 +S4 +F70 +E2 +F73 +S4 +F71 +L90 +E1 +S3 +E5 +N3 +E2 +N5 +L270 +F69 +E5 +F30 +N1 +R90 +N4 +F15 +E4 +R180 +F12 +E2 +F95 +E2 +S4 +F13 +S1 +E1 +N4 +E3 +L270 +E4 +S5 +E3 +N2 +R180 +S2 +W2 +L90 +S3 +W4 +R90 +E1 +L180 +W5 +F23 +E5 +F67 +R90 +N2 +W4 +L90 +S1 +L90 +F17 +W2 +F80 +E1 +F13 +S2 +E3 +S4 +F46 +F70 +R180 +E3 +L90 +E4 +L90 +S3 +F31 +W5 +R90 +F21 +S5 +L90 +F12 +L90 +F70 +S1 +R180 +W5 +F14 +S5 +W5 +S1 +F56 +L90 +F43 +S4 +N4 +E1 +R180 +S1 +R90 +E3 +N4 +R90 +S2 +E5 +S4 +W4 +R90 +F88 +S4 +R90 +F79 +L90 +N2 +E3 +F74 +L90 +F72 +W1 +N3 +R90 +E2 +F38 +W3 +L90 +E3 +N2 +R90 +E2 +L90 +N3 +E1 +F96 +E3 +S4 +R180 +F28 +S2 +F93 +L270 +N3 +R90 +N2 +E4 +S1 +F47 +L270 +F9 +N2 +F80 +S4 +L180 +N5 +W2 +L90 +W4 +N5 +L90 +F82 +R90 +N3 +F4 +R90 +F96 +W5 +R90 +F28 +W2 +S2 +F16 +S4 +R90 +F9 +N5 +W4 +F78 +E3 +F84 +L90 +F42 +W2 +F43 +W4 +L90 +F95 +E1 +R90 +F59 +L90 +F82 +W1 +F17 +S4 +R180 +F91 +L180 +N1 +R90 +N3 +F57 +L90 +F90 +N3 +R90 +F98 +N5 +R90 +N2 +R90 +F4 +S2 +F80 +S2 +N2 +W4 +L90 +E2 +F67 +R90 +W4 +L180 +F22 +L90 +S3 +F9 +N5 +W2 +L180 +S3 +F23 +S4 +W4 +F90 +S2 +F32 +S3 +E5 +R90 +E1 +F64 +R180 +F17 +E3 +R90 +N2 +E1 +F90 +W3 +N5 +F19 +S5 +E4 +N5 +R90 +W1 +F18 +R180 +E2 +R90 +F76 +L90 +N2 +F96 +F38 +R180 +F94 +S4 +W4 +S4 +F63 +E4 +L90 +F69 +S2 +W3 +N1 +L270 +N1 +L90 +N4 +R90 +E5 +F67 +F85 +S1 +F2 +F68 +W2 +R90 +E4 +R90 +S3 +W4 +S2 +N5 +F13 +R180 +W1 +F31 +S1 +F23 +S1 +R90 +F86 +L90 +N5 +W3 +F47 +R90 +R270 +S1 +L90 +S1 +F40 +N4 +R180 +N1 +L180 +W3 +S1 +W5 +L90 +W5 +F41 +S4 +E2 +N5 +E4 +N1 +F97 +L90 +F62 +N5 +R90 +F98 +R180 +S5 +L270 +N5 +W5 +N4 +E3 +F38 +L90 +S2 +F79 +R270 +E1 +F14 +W1 +F38 +E3 +L180 +N4 +L90 +S5 +F90 +S1 +F7 +N1 +F11 +W4 +R180 +F73 +L90 +F54 +F25 +W5 +S3 +F39 +E2 +F37 +E2 +S4 +F94 +W5 +S2 +L180 +W3 +F70 +S3 +R180 +W1 +N5 +R90 +S4 +F12 +S3 +F45 +E1 +N3 +R90 +S2 +L180 +E4 +S3 +W5 +F9 +S4 +R90 +F19 +W3 +N4 +W5 +R90 +F16 +W3 +S4 +W1 +S3 +R180 +S4 +E4 +N1 +W3 +F10 +N5 +E2 +F61 +E4 +S1 +W3 +N5 +W2 +L90 +W5 +N2 +W1 +F8 +W4 +S5 +L180 +F76 +N1 +R180 +S3 +R180 +S3 +E1 +R90 +W1 +F38 +R90 +F74 +N2 +F60 +L90 +E2 +S3 +F78 +W1 +F57 +R90 +F39 +N5 +F2 +E3 +R90 +F81 +E2 +F2 +S3 +R90 +F95 +S4 +F1 +E2 +N5 +L270 +F59 +W2 +R90 +S1 +F42 +E2 +N5 +E4 +L90 +W1 +F17 +E2 +F91 +R90 +E3 +F30 +S1 +R90 +W5 +F74 +W5 +N1 +N4 +R180 +S5 +R180 +F92 +N4 +N3 +E3 +R90 +F60 +S4 +L90 +E4 +R270 +F3 +E1 +L180 +E1 +S5 +F84 +E3 +L90 +N3 +F27 +W1 +F58 +N1 +F93 +N2 +F30 +L90 +N2 +L90 +N2 +F99 +W4 +S2 +F13 +L90 +N3 +W4 +F100 diff --git a/src/day12.rs b/src/day12.rs new file mode 100644 index 0000000..c0aad79 --- /dev/null +++ b/src/day12.rs @@ -0,0 +1,148 @@ +use aoc_runner_derive::aoc; + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum LeftRight { + Left, + Right, +} + +#[derive(Debug, Copy, Clone)] +#[repr(u8)] +enum Direction { + North = 0, + East = 1, + South = 2, + West = 3, +} + +impl Direction { + fn xy(self) -> (isize, isize) { + match self { + Direction::North => (0, 1), + Direction::East => (1, 0), + Direction::South => (0, -1), + Direction::West => (-1, 0), + } + } + + fn from_usize(x: usize) -> Self { + match x { + 0 => Direction::North, + 1 => Direction::East, + 2 => Direction::South, + 3 => Direction::West, + _ => panic!("invalid direction"), + } + } + + fn rotate_ship(self, degrees: usize, lr: LeftRight) -> Self { + debug_assert!(degrees % 90 == 0); + let num_turns = degrees / 90; + Direction::from_usize(match lr { + LeftRight::Left => (self as usize).wrapping_sub(num_turns) & 0b11, + LeftRight::Right => (self as usize).wrapping_add(num_turns) & 0b11, + }) + } +} + +enum Action { + North(usize), + East(usize), + South(usize), + West(usize), + Left(usize), + Right(usize), + Forward(usize), +} + +impl Action { + fn parse(input: &str) -> Option { + let value = (&input[1..]).parse().ok()?; + Some(match input.as_bytes()[0] { + b'N' => Action::North(value), + b'E' => Action::East(value), + b'S' => Action::South(value), + b'W' => Action::West(value), + b'L' => Action::Left(value), + b'R' => Action::Right(value), + b'F' => Action::Forward(value), + _ => return None, + }) + } +} + +#[aoc(day12, part1)] +fn solve_d12_p1(input: &str) -> usize { + let mut x = 0isize; + let mut y = 0isize; + let mut ship_dir = Direction::East; + for action in input.split('\n').map(|x| Action::parse(x).unwrap()) { + match action { + Action::North(distance) => y += distance as isize, + Action::East(distance) => x += distance as isize, + Action::South(distance) => y -= distance as isize, + Action::West(distance) => x -= distance as isize, + Action::Left(degrees) => ship_dir = ship_dir.rotate_ship(degrees, LeftRight::Left), + Action::Right(degrees) => ship_dir = ship_dir.rotate_ship(degrees, LeftRight::Right), + Action::Forward(distance) => { + let (x_step, y_step) = ship_dir.xy(); + x += x_step * distance as isize; + y += y_step * distance as isize; + } + } + } + x.abs() as usize + y.abs() as usize +} + +#[derive(Debug, Copy, Clone)] +struct Waypoint { + x: isize, + y: isize, +} + +impl Waypoint { + fn rotate(self, mut degrees: usize, lr: LeftRight) -> Self { + assert!(degrees == 90 || degrees == 180 || degrees == 270); + if lr == LeftRight::Left { + degrees = 360 - degrees; + } + match degrees { + 0 => self, + 90 => Waypoint { + x: self.y, + y: -self.x, + }, + 180 => Waypoint { + x: -self.x, + y: -self.y, + }, + 270 => Waypoint { + x: -self.y, + y: self.x, + }, + _ => unreachable!(), + } + } +} + +#[aoc(day12, part2)] +fn solve_d12_p2(input: &str) -> usize { + let mut waypoint = Waypoint { x: 10, y: 1 }; + let mut x = 0isize; + let mut y = 0isize; + for action in input.split('\n').map(|x| Action::parse(x).unwrap()) { + match action { + Action::North(distance) => waypoint.y += distance as isize, + Action::East(distance) => waypoint.x += distance as isize, + Action::South(distance) => waypoint.y -= distance as isize, + Action::West(distance) => waypoint.x -= distance as isize, + Action::Left(degrees) => waypoint = waypoint.rotate(degrees, LeftRight::Left), + Action::Right(degrees) => waypoint = waypoint.rotate(degrees, LeftRight::Right), + Action::Forward(distance) => { + x += waypoint.x * distance as isize; + y += waypoint.y * distance as isize; + } + } + } + x.abs() as usize + y.abs() as usize +} diff --git a/src/lib.rs b/src/lib.rs index 9aa3dcd..93b2826 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ pub mod day1; pub mod day10; pub mod day11; +pub mod day12; pub mod day2; pub mod day3; pub mod day4;