Last active
February 3, 2024 14:26
-
-
Save MikuroXina/4c24802f16bfab4a0f7698bb9586b250 to your computer and use it in GitHub Desktop.
Definition of coordinate and orientation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | |
| pub struct Field { | |
| // both of width and height must ≤ i64::MAX for safety | |
| width: u64, | |
| height: u64, | |
| } | |
| impl Field { | |
| pub fn new(width: u64, height: u64) -> Self { | |
| assert!( | |
| width <= i64::MAX as u64, | |
| "`width` must less than or equal to i64::MAX for safety" | |
| ); | |
| assert!( | |
| height <= i64::MAX as u64, | |
| "`height` must less than or equal to i64::MAX for safety" | |
| ); | |
| Self { width, height } | |
| } | |
| pub fn on(&self, x: u64, y: u64) -> Option<Coord> { | |
| Coord::with_x_y(self, x, y) | |
| } | |
| } | |
| #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | |
| pub struct Coord<'a> { | |
| x: u64, // +X is east | |
| y: u64, // +Y is south | |
| field: &'a Field, | |
| } | |
| impl<'a> Coord<'a> { | |
| pub fn new(field: &'a Field) -> Self { | |
| Self { x: 0, y: 0, field } | |
| } | |
| pub fn with_x_y(field: &'a Field, x: u64, y: u64) -> Option<Self> { | |
| (x < field.width && y < field.height).then_some(Self { x, y, field }) | |
| } | |
| pub fn advance_to(self, orient: Orientation) -> Option<Self> { | |
| match orient { | |
| Orientation::North => (self.y > 0).then(|| Self { | |
| y: self.y - 1, | |
| ..self | |
| }), | |
| Orientation::West => (self.x > 0).then(|| Self { | |
| x: self.x - 1, | |
| ..self | |
| }), | |
| Orientation::South => (self.y + 1 < self.field.height).then_some(Self { | |
| y: self.y + 1, | |
| ..self | |
| }), | |
| Orientation::East => (self.x + 1 < self.field.width).then_some(Self { | |
| x: self.x + 1, | |
| ..self | |
| }), | |
| } | |
| } | |
| pub fn around(self) -> impl Iterator<Item = Coord<'a>> { | |
| Orientation::all() | |
| .into_iter() | |
| .flat_map(move |orient| self.advance_to(orient)) | |
| } | |
| } | |
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | |
| pub enum Orientation { | |
| North, | |
| West, | |
| South, | |
| East, | |
| } | |
| impl Orientation { | |
| pub fn all() -> [Self; 4] { | |
| [ | |
| Orientation::North, | |
| Orientation::West, | |
| Orientation::South, | |
| Orientation::East, | |
| ] | |
| } | |
| pub fn turn_right(self) -> Self { | |
| match self { | |
| Self::North => Self::West, | |
| Self::West => Self::South, | |
| Self::South => Self::East, | |
| Self::East => Self::North, | |
| } | |
| } | |
| pub fn turn_left(self) -> Self { | |
| match self { | |
| Self::North => Self::East, | |
| Self::West => Self::North, | |
| Self::South => Self::West, | |
| Self::East => Self::South, | |
| } | |
| } | |
| pub fn opposite(self) -> Self { | |
| match self { | |
| Self::North => Self::South, | |
| Self::West => Self::East, | |
| Self::South => Self::North, | |
| Self::East => Self::West, | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment