@@ -6,19 +6,6 @@ pub struct DirectedPos {
66 dir : Direction ,
77}
88
9- #[ repr( u8 ) ]
10- #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
11- pub enum Direction {
12- North = 0 ,
13- NorthEast = 1 ,
14- East = 2 ,
15- SouthEast = 3 ,
16- South = 4 ,
17- SouthWest = 5 ,
18- West = 6 ,
19- NorthWest = 7 ,
20- }
21-
229impl DirectedPos {
2310 pub fn new ( pos : Pos , dir : Direction ) -> Self {
2411 Self { pos, dir }
@@ -48,6 +35,46 @@ impl DirectedPos {
4835 self . pos . col ( )
4936 }
5037
38+ /// Rotate direction by 90 degrees clockwise
39+ pub fn cw ( self ) -> Self {
40+ Self {
41+ pos : self . pos ,
42+ dir : self . dir . cw ( ) ,
43+ }
44+ }
45+
46+ /// Rotate direction by 90 degrees counter-clockwise
47+ pub fn ccw ( self ) -> Self {
48+ Self {
49+ pos : self . pos ,
50+ dir : self . dir . ccw ( ) ,
51+ }
52+ }
53+
54+ /// Rotate direction by 45 degrees clockwise
55+ pub fn cw45 ( self ) -> Self {
56+ Self {
57+ pos : self . pos ,
58+ dir : self . dir . cw45 ( ) ,
59+ }
60+ }
61+
62+ /// Rotate direction by 45 degrees counter-clockwise
63+ pub fn ccw45 ( self ) -> Self {
64+ Self {
65+ pos : self . pos ,
66+ dir : self . dir . ccw45 ( ) ,
67+ }
68+ }
69+
70+ /// Rotate direction by 180 degrees
71+ pub fn reverse ( self ) -> Self {
72+ Self {
73+ pos : self . pos ,
74+ dir : self . dir . reverse ( ) ,
75+ }
76+ }
77+
5178 pub fn north ( & self , grid : & Grid ) -> Option < DirectedPos > {
5279 self . pos . north ( grid) . map ( |p| Self :: new ( p, self . dir ) )
5380 }
@@ -81,9 +108,66 @@ impl DirectedPos {
81108 }
82109}
83110
111+ #[ repr( u8 ) ]
112+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
113+ pub enum Direction {
114+ North = 0 ,
115+ NorthEast = 1 ,
116+ East = 2 ,
117+ SouthEast = 3 ,
118+ South = 4 ,
119+ SouthWest = 5 ,
120+ West = 6 ,
121+ NorthWest = 7 ,
122+ }
123+
124+ impl Direction {
125+ /// Rotate by 90 degrees clockwise
126+ pub fn cw ( self ) -> Self {
127+ Self :: cast ( ( self as u8 ) + 2 )
128+ }
129+
130+ /// Rotate by 90 degrees counter-clockwise
131+ pub fn ccw ( self ) -> Self {
132+ Self :: cast ( ( self as u8 ) + 6 )
133+ }
134+
135+ /// Rotate by 45 degrees clockwise
136+ pub fn cw45 ( self ) -> Self {
137+ Self :: cast ( ( self as u8 ) + 1 )
138+ }
139+
140+ /// Rotate by 45 degrees counter-clockwise
141+ pub fn ccw45 ( self ) -> Self {
142+ Self :: cast ( ( self as u8 ) + 7 )
143+ }
144+
145+ /// Rotate by 180 degrees
146+ pub fn reverse ( self ) -> Self {
147+ Self :: cast ( ( self as u8 ) + 4 )
148+ }
149+
150+ fn cast ( val : u8 ) -> Self {
151+ let mask = 7 ;
152+
153+ match val & mask {
154+ 0 => Self :: North ,
155+ 1 => Self :: NorthEast ,
156+ 2 => Self :: East ,
157+ 3 => Self :: SouthEast ,
158+ 4 => Self :: South ,
159+ 5 => Self :: SouthWest ,
160+ 6 => Self :: West ,
161+ 7 => Self :: NorthWest ,
162+ _ => unreachable ! ( ) ,
163+ }
164+ }
165+ }
166+
84167#[ cfg( test) ]
85168mod test {
86169 use super :: * ;
170+ use std:: iter;
87171
88172 #[ test]
89173 fn test_pos ( ) {
@@ -97,4 +181,17 @@ mod test {
97181 DirectedPos :: new( grid. pos( 1 ) , Direction :: North )
98182 ) ;
99183 }
184+
185+ #[ test]
186+ fn test_rotations ( ) {
187+ let grid = Grid :: new ( "012\n 345\n 678" . to_string ( ) ) ;
188+ let first_pos = DirectedPos :: new ( grid. pos ( 4 ) , Direction :: North ) ;
189+
190+ for pos in iter:: successors ( Some ( first_pos) , |p| Some ( p. cw45 ( ) ) ) . take ( 8 ) {
191+ assert_eq ! ( pos, pos. cw( ) . ccw( ) ) ;
192+ assert_eq ! ( pos, pos. cw( ) . ccw45( ) . ccw45( ) ) ;
193+ assert_eq ! ( pos, pos. ccw( ) . cw45( ) . cw45( ) ) ;
194+ assert_eq ! ( pos. cw( ) . cw( ) , pos. reverse( ) ) ;
195+ }
196+ }
100197}
0 commit comments