2020: day12: refacto coordinates system

This commit is contained in:
Antoine Martin 2020-12-12 17:01:58 +01:00
parent 1f0eeb3b04
commit f85bea7bb4

View file

@ -149,10 +149,26 @@ impl std::str::FromStr for Action {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Ship { struct Coordinates {
direction: Direction,
x: i64, x: i64,
y: i64, y: i64,
}
impl Coordinates {
fn move_towards(&mut self, direction: Direction, distance: i64) {
match direction {
Direction::North => self.y -= distance,
Direction::South => self.y += distance,
Direction::West => self.x -= distance,
Direction::East => self.x += distance,
}
}
}
#[derive(Debug, Clone)]
struct Ship {
direction: Direction,
coordinates: Coordinates,
waypoint: Waypoint, waypoint: Waypoint,
} }
@ -161,36 +177,35 @@ impl Ship {
fn new() -> Self { fn new() -> Self {
Self { Self {
direction: Direction::East, direction: Direction::East,
x: 0, coordinates: Coordinates { x: 0, y: 0 },
y: 0,
waypoint: Waypoint::new(), waypoint: Waypoint::new(),
} }
} }
fn manhattan_distance(&self) -> i64 { fn manhattan_distance(&self) -> i64 {
self.x.abs() + self.y.abs() self.coordinates.x.abs() + self.coordinates.y.abs()
} }
fn process(&mut self, action: Action) { fn process(&mut self, action: Action) {
match action.kind { match action.kind {
ActionKind::Move(dir) => self.forward(dir, action.arg), ActionKind::Move(dir) => self.coordinates.move_towards(dir, action.arg as i64),
ActionKind::Turn(turn_dir) => { ActionKind::Turn(turn_dir) => {
self.direction = self.direction.rotate(turn_dir, action.arg); self.direction = self.direction.rotate(turn_dir, action.arg);
} }
ActionKind::Forward => self.forward(self.direction, action.arg), ActionKind::Forward => self
.coordinates
.move_towards(self.direction, action.arg as i64),
} }
} }
fn process_with_waypoint(&mut self, action: Action) { fn process_with_waypoint(&mut self, action: Action) {
match action.kind { match action.kind {
ActionKind::Move(dir) => match dir { ActionKind::Move(dir) => self
Direction::North => self.waypoint.y -= action.arg as i64, .waypoint
Direction::South => self.waypoint.y += action.arg as i64, .coordinates
Direction::West => self.waypoint.x -= action.arg as i64, .move_towards(dir, action.arg as i64),
Direction::East => self.waypoint.x += action.arg as i64,
},
ActionKind::Turn(turn_dir) => { ActionKind::Turn(turn_dir) => {
debug_assert!(action.arg % 90 == 0, "only right angles are supported"); debug_assert!(action.arg % 90 == 0, "only right angles are supported");
@ -202,43 +217,36 @@ impl Ship {
ActionKind::Forward => { ActionKind::Forward => {
let (west_east, north_south) = self.waypoint.as_dirs(); let (west_east, north_south) = self.waypoint.as_dirs();
let (dx, dy) = self.waypoint.diff();
self.forward(west_east, self.waypoint.x.abs() as u16 * action.arg); self.coordinates
self.forward(north_south, self.waypoint.y.abs() as u16 * action.arg); .move_towards(west_east, dx * action.arg as i64);
self.coordinates
.move_towards(north_south, dy * action.arg as i64);
} }
} }
} }
fn forward(&mut self, direction: Direction, arg: u16) {
let arg = arg as i64;
match direction {
Direction::North => self.y -= arg as i64,
Direction::South => self.y += arg as i64,
Direction::West => self.x -= arg as i64,
Direction::East => self.x += arg as i64,
}
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct Waypoint { struct Waypoint {
x: i64, coordinates: Coordinates,
y: i64,
} }
impl Waypoint { impl Waypoint {
fn new() -> Self { fn new() -> Self {
Self { x: 10, y: -1 } Self {
coordinates: Coordinates { x: 10, y: -1 },
}
} }
fn as_dirs(&self) -> (Direction, Direction) { fn as_dirs(&self) -> (Direction, Direction) {
let west_east = if self.x < 0 { let west_east = if self.coordinates.x < 0 {
Direction::West Direction::West
} else { } else {
Direction::East Direction::East
}; };
let north_south = if self.y < 0 { let north_south = if self.coordinates.y < 0 {
Direction::North Direction::North
} else { } else {
Direction::South Direction::South
@ -247,18 +255,27 @@ impl Waypoint {
(west_east, north_south) (west_east, north_south)
} }
fn diff(&self) -> (i64, i64) {
(
self.coordinates.x.abs() as i64,
self.coordinates.y.abs() as i64,
)
}
fn turn(&mut self, turn_dir: TurnDirection, quadrants: usize) { fn turn(&mut self, turn_dir: TurnDirection, quadrants: usize) {
let coords = &mut self.coordinates;
for _ in 0..quadrants { for _ in 0..quadrants {
let mut x = self.x; let mut x = coords.x;
let mut y = self.y; let mut y = coords.y;
match turn_dir { match turn_dir {
TurnDirection::Left => x = -x, TurnDirection::Left => x = -x,
TurnDirection::Right => y = -y, TurnDirection::Right => y = -y,
} }
self.x = y; coords.x = y;
self.y = x; coords.y = x;
} }
} }
} }