diff --git a/2020/src/bin/day12.rs b/2020/src/bin/day12.rs index 01c052b..87a3499 100644 --- a/2020/src/bin/day12.rs +++ b/2020/src/bin/day12.rs @@ -18,23 +18,23 @@ fn parse_input(raw: &str) -> Parsed { fn part1(parsed: &Parsed) -> i64 { let end_pos = parsed .iter() - .fold((Direction::Right, Position2D { x: 0, y: 0 }), |(dir, pos), (cmd, dist)| match cmd { - 'N' => (dir, pos + Position2D::from((0, *dist))), - 'S' => (dir, pos - Position2D::from((0, *dist))), - 'E' => (dir, pos + Position2D::from((*dist, 0))), - 'W' => (dir, pos - Position2D::from((*dist, 0))), + .fold((Direction::Right, PositionND::from([0, 0])), |(dir, pos), (cmd, dist)| match cmd { + 'N' => (dir, pos + PositionND::from([0, *dist])), + 'S' => (dir, pos - PositionND::from([0, *dist])), + 'E' => (dir, pos + PositionND::from([*dist, 0])), + 'W' => (dir, pos - PositionND::from([*dist, 0])), 'R' => (dir + (dist / 90) as i8, pos), 'L' => (dir + -(dist / 90) as i8, pos), - 'F' => (dir, pos + Position2D::from(dir) * *dist), + 'F' => (dir, pos + PositionND::from(dir) * *dist), _ => unreachable!(), }) .1; - end_pos.x.abs() + end_pos.y.abs() + end_pos.points[0].abs() + end_pos.points[1].abs() } -fn rotate_waypoint(mut wp: Position2D, deg: i64) -> Position2D { +fn rotate_waypoint(mut wp: PositionND<2>, deg: i64) -> PositionND<2> { for _ in 0..((deg / 90 + 4) & 3) { - wp = Position2D { x: wp.y, y: -wp.x }; + wp = PositionND::from([wp.points[1], -wp.points[0]]); } wp } @@ -43,12 +43,12 @@ fn part2(parsed: &Parsed) -> i64 { let end_pos = parsed .iter() .fold( - (Position2D { x: 10, y: 1 }, Position2D { x: 0, y: 0 }), + (PositionND::from([10, 1]), PositionND::from([0, 0])), |(wp, pos), (cmd, dist)| match cmd { - 'N' => (wp + Position2D::from((0, *dist)), pos), - 'S' => (wp - Position2D::from((0, *dist)), pos), - 'E' => (wp + Position2D::from((*dist, 0)), pos), - 'W' => (wp - Position2D::from((*dist, 0)), pos), + 'N' => (wp + PositionND::from([0, *dist]), pos), + 'S' => (wp - PositionND::from([0, *dist]), pos), + 'E' => (wp + PositionND::from([*dist, 0]), pos), + 'W' => (wp - PositionND::from([*dist, 0]), pos), 'R' => (rotate_waypoint(wp, *dist), pos), 'L' => (rotate_waypoint(wp, -dist), pos), 'F' => (wp, pos + wp * *dist), @@ -56,7 +56,7 @@ fn part2(parsed: &Parsed) -> i64 { }, ) .1; - end_pos.x.abs() + end_pos.y.abs() + end_pos.points[0].abs() + end_pos.points[1].abs() } fn main() { diff --git a/2020/src/grid/position.rs b/2020/src/grid/position.rs index 92df969..8c4eb46 100644 --- a/2020/src/grid/position.rs +++ b/2020/src/grid/position.rs @@ -3,7 +3,7 @@ use super::direction::*; use impl_ops::*; use itertools::iproduct; use std::{ - convert::TryInto, hash::Hash, ops::{self, Add, AddAssign, Mul} + convert::TryInto, hash::Hash, ops::{self, Add, AddAssign, Mul, Sub} }; pub trait Position @@ -151,6 +151,29 @@ impl Add> for PositionND { } } +impl Sub> for PositionND { + type Output = PositionND; + + fn sub(self, rhs: PositionND) -> Self::Output { + let mut points = [0; D]; + for i in 0..D { + points[i] = self.points[i] - rhs.points[i]; + } + PositionND { points } + } +} + +impl From for PositionND<2> { + fn from(d: Direction) -> Self { + match d { + Direction::Up => PositionND::from([0, 1]), + Direction::Right => PositionND::from([1, 0]), + Direction::Left => PositionND::from([-1, 0]), + Direction::Down => PositionND::from([0, -1]), + } + } +} + mod p2d { use super::*;