1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use std::{ cmp::Ordering, ops::{Add, AddAssign, Sub}, }; #[derive(Clone, Copy, Eq, PartialEq, Debug, Hash)] pub struct Point { pub row: u32, pub column: u32, } impl Point { pub fn new(row: u32, column: u32) -> Self { Self { row, column } } pub fn zero() -> Self { Point::new(0, 0) } pub fn is_zero(&self) -> bool { self.row == 0 && self.column == 0 } } impl<'a> Add<&'a Self> for Point { type Output = Point; fn add(self, other: &'a Self) -> Self::Output { if other.row == 0 { Point::new(self.row, self.column + other.column) } else { Point::new(self.row + other.row, other.column) } } } impl<'a> Sub<&'a Self> for Point { type Output = Point; fn sub(self, other: &'a Self) -> Self::Output { debug_assert!(*other <= self); if self.row == other.row { Point::new(0, self.column - other.column) } else { Point::new(self.row - other.row, self.column) } } } impl<'a> AddAssign<&'a Self> for Point { fn add_assign(&mut self, other: &'a Self) { if other.row == 0 { self.column += other.column; } else { self.row += other.row; self.column = other.column; } } } impl PartialOrd for Point { fn partial_cmp(&self, other: &Point) -> Option<Ordering> { Some(self.cmp(other)) } } impl Ord for Point { fn cmp(&self, other: &Self) -> Ordering { let a = (self.row as usize) << 32 | self.column as usize; let b = (other.row as usize) << 32 | other.column as usize; a.cmp(&b) } }