1use std::fmt::{Display, Formatter};
2
3#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
5pub enum Dir {
6 North,
7 East,
8 South,
9 West,
10}
11
12impl Dir {
13 pub const ALL: [Dir; 4] = [Dir::North, Dir::East, Dir::South, Dir::West];
17}
18
19impl Dir {
20 pub const fn opposite(self) -> Self {
24 match self {
25 Dir::North => Dir::South,
26 Dir::East => Dir::West,
27 Dir::South => Dir::North,
28 Dir::West => Dir::East,
29 }
30 }
31
32 pub const fn left(self) -> Self {
34 match self {
35 Dir::North => Dir::West,
36 Dir::East => Dir::North,
37 Dir::South => Dir::East,
38 Dir::West => Dir::South,
39 }
40 }
41
42 pub const fn right(self) -> Self {
44 match self {
45 Dir::North => Dir::East,
46 Dir::East => Dir::South,
47 Dir::South => Dir::West,
48 Dir::West => Dir::North,
49 }
50 }
51}
52
53impl Display for Dir {
54 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55 write!(f, "{:?}", self)
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use crate::Dir;
62
63 #[test]
64 fn opposite_roundtrip() {
65 for dir in Dir::ALL {
66 assert_eq!(dir.opposite().opposite(), dir);
67 }
68 }
69
70 #[test]
71 fn opposite_not_self() {
72 for dir in Dir::ALL {
73 assert_ne!(dir.opposite(), dir);
74 }
75 }
76
77 #[test]
78 fn left_right_inverse() {
79 for dir in Dir::ALL {
80 assert_eq!(dir.left().right(), dir);
81 assert_eq!(dir.right().left(), dir);
82 }
83 }
84
85 #[test]
86 fn four_rights_make_a_circle() {
87 for dir in Dir::ALL {
88 assert_eq!(dir.right().right().right().right(), dir);
89 }
90 }
91
92 #[test]
93 fn four_lefts_make_a_circle() {
94 for dir in Dir::ALL {
95 assert_eq!(dir.left().left().left().left(), dir);
96 }
97 }
98
99 #[test]
100 fn all_unique() {
101 for (i, a) in Dir::ALL.iter().enumerate() {
102 for (j, b) in Dir::ALL.iter().enumerate() {
103 if i != j {
104 assert_ne!(a, b);
105 }
106 }
107 }
108 }
109}