Skip to content

Instantly share code, notes, and snippets.

@MikuroXina
Last active February 3, 2024 14:26
Show Gist options
  • Select an option

  • Save MikuroXina/4c24802f16bfab4a0f7698bb9586b250 to your computer and use it in GitHub Desktop.

Select an option

Save MikuroXina/4c24802f16bfab4a0f7698bb9586b250 to your computer and use it in GitHub Desktop.
Definition of coordinate and orientation.
#[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