Advent of Code solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at db70ca7fa220d0320b47036e7aa38273645acd18 146 lines 4.4 kB view raw
1/// Module containing utilities related to direction and movement. 2use crate::pos::Position; 3 4/// Trait used to define an object that can be used to move around a grid. 5/// 6/// This is meant for complex scenarios where you want to move around a grid in a non-standard way. 7/// By implementing this trait you can use various methods from the [Position] struct to move around. 8/// 9/// # Implementing 10/// 11/// Implementing this trait requires you to define a `get_kernel` method that returns a `Position`. 12/// This position is used to move around the grid by applying it to the current position. 13/// 14/// # Examples 15/// 16/// ``` 17/// use utils::prelude::*; 18/// 19/// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 20/// struct RightBy(usize); 21/// 22/// impl Movement for RightBy { 23/// fn get_kernel(&self) -> Position { 24/// Position::new(self.0 as isize, 0) 25/// } 26/// } 27/// 28/// let pos = Position::new(0, 0); 29/// assert_eq!(pos.move_dir(RightBy(1)), Position::new(1, 0)); 30/// ``` 31/// 32/// # See also 33/// 34/// - [Direction] is a simple implementation of this trait. 35/// - [Position] is the main user of this trait. 36/// 37pub trait Movement: std::fmt::Debug + Copy + Clone + PartialEq + std::hash::Hash { 38 fn get_kernel(&self) -> Position; 39} 40 41/// The four cardinal directions. 42/// Useful for iterating over all four directions. 43pub const CARDINALS: [Direction; 4] = [ 44 Direction::North, 45 Direction::South, 46 Direction::East, 47 Direction::West, 48]; 49 50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] 51/// The four cardinal directions. 52/// This is a simple implementation of the [Movement] trait. 53/// 54/// # Examples 55/// 56/// ``` 57/// use utils::prelude::*; 58/// 59/// let pos = Position::new(0, 0); 60/// assert_eq!(pos.move_dir(Direction::North), Position::new(0, -1)); 61/// assert_eq!(pos.move_dir(Direction::South), Position::new(0, 1)); 62/// assert_eq!(pos.move_dir(Direction::East), Position::new(1, 0)); 63/// assert_eq!(pos.move_dir(Direction::West), Position::new(-1, 0)); 64/// ``` 65/// 66pub enum Direction { 67 North, 68 South, 69 East, 70 West, 71} 72 73impl Direction { 74 /// Returns the direction that is opposite to the current one. 75 /// 76 /// # Examples 77 /// 78 /// ``` 79 /// use utils::prelude::*; 80 /// 81 /// assert_eq!(Direction::North.opposite(), Direction::South); 82 /// assert_eq!(Direction::South.opposite(), Direction::North); 83 /// assert_eq!(Direction::East.opposite(), Direction::West); 84 /// assert_eq!(Direction::West.opposite(), Direction::East); 85 /// ``` 86 /// 87 pub fn opposite(&self) -> Self { 88 match self { 89 Self::North => Self::South, 90 Self::South => Self::North, 91 Self::East => Self::West, 92 Self::West => Self::East, 93 } 94 } 95 96 /// Returns the direction that is 90 degrees to the current one. 97 /// 98 /// # Examples 99 /// 100 /// ``` 101 /// use utils::prelude::*; 102 /// 103 /// assert_eq!(Direction::North.ninety_deg(true), Direction::East); 104 /// assert_eq!(Direction::North.ninety_deg(false), Direction::West); 105 /// 106 /// assert_eq!(Direction::South.ninety_deg(true), Direction::West); 107 /// assert_eq!(Direction::South.ninety_deg(false), Direction::East); 108 /// ``` 109 /// 110 pub fn ninety_deg(&self, clockwise: bool) -> Self { 111 match (self, clockwise) { 112 (Self::North, true) => Self::East, 113 (Self::North, false) => Self::West, 114 (Self::South, true) => Self::West, 115 (Self::South, false) => Self::East, 116 (Self::East, true) => Self::South, 117 (Self::East, false) => Self::North, 118 (Self::West, true) => Self::North, 119 (Self::West, false) => Self::South, 120 } 121 } 122} 123 124impl From<Position> for Direction { 125 fn from(pos: Position) -> Self { 126 let pos = pos.normalize(); 127 match (pos.x, pos.y) { 128 (0, -1) => Self::North, 129 (0, 1) => Self::South, 130 (1, 0) => Self::East, 131 (-1, 0) => Self::West, 132 _ => panic!("Invalid position"), 133 } 134 } 135} 136 137impl Movement for Direction { 138 fn get_kernel(&self) -> Position { 139 match self { 140 Direction::North => Position::new(0, -1), 141 Direction::South => Position::new(0, 1), 142 Direction::East => Position::new(1, 0), 143 Direction::West => Position::new(-1, 0), 144 } 145 } 146}