1use std::hash::{Hash, Hasher};
28use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
29
30pub const ORIGIN: Point = Point::new(0, 0);
31pub const UP: Point = Point::new(0, -1);
32pub const DOWN: Point = Point::new(0, 1);
33pub const LEFT: Point = Point::new(-1, 0);
34pub const RIGHT: Point = Point::new(1, 0);
35pub const ORTHOGONAL: [Point; 4] = [UP, DOWN, LEFT, RIGHT];
36pub const DIAGONAL: [Point; 8] = [
38 Point::new(-1, -1),
39 UP,
40 Point::new(1, -1),
41 LEFT,
42 RIGHT,
43 Point::new(-1, 1),
44 DOWN,
45 Point::new(1, 1),
46];
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub struct Point {
50 pub x: i32,
51 pub y: i32,
52}
53
54impl Point {
55 #[inline]
56 #[must_use]
57 pub const fn new(x: i32, y: i32) -> Self {
58 Self { x, y }
59 }
60
61 #[inline]
62 #[must_use]
63 pub fn clockwise(self) -> Self {
64 Self::new(-self.y, self.x)
65 }
66
67 #[inline]
68 #[must_use]
69 pub fn counter_clockwise(self) -> Self {
70 Self::new(self.y, -self.x)
71 }
72
73 #[inline]
74 #[must_use]
75 pub fn manhattan(self, other: Self) -> i32 {
76 (self.x - other.x).abs() + (self.y - other.y).abs()
77 }
78}
79
80impl From<u8> for Point {
81 #[inline]
82 fn from(value: u8) -> Self {
83 match value {
84 b'^' | b'U' => UP,
85 b'v' | b'D' => DOWN,
86 b'<' | b'L' => LEFT,
87 b'>' | b'R' => RIGHT,
88 _ => unreachable!(),
89 }
90 }
91}
92
93impl Hash for Point {
94 #[inline]
95 fn hash<H: Hasher>(&self, state: &mut H) {
96 state.write_u32(self.x as u32);
97 state.write_u32(self.y as u32);
98 }
99}
100
101impl Add for Point {
102 type Output = Self;
103
104 #[inline]
105 fn add(self, rhs: Self) -> Self {
106 Self::new(self.x + rhs.x, self.y + rhs.y)
107 }
108}
109
110impl AddAssign for Point {
111 #[inline]
112 fn add_assign(&mut self, rhs: Self) {
113 self.x += rhs.x;
114 self.y += rhs.y;
115 }
116}
117
118impl Mul<i32> for Point {
119 type Output = Self;
120
121 #[inline]
122 fn mul(self, rhs: i32) -> Self {
123 Self::new(self.x * rhs, self.y * rhs)
124 }
125}
126
127impl Sub for Point {
128 type Output = Self;
129
130 #[inline]
131 fn sub(self, rhs: Self) -> Self {
132 Self::new(self.x - rhs.x, self.y - rhs.y)
133 }
134}
135
136impl SubAssign for Point {
137 #[inline]
138 fn sub_assign(&mut self, rhs: Self) {
139 self.x -= rhs.x;
140 self.y -= rhs.y;
141 }
142}