@@ -7,29 +7,24 @@ pub struct Day01;
77
88impl Solution for Day01 {
99 fn part_one ( & self , input : & str ) -> String {
10- self . run ( input) . stops_at_zero ( ) . to_string ( )
10+ SafeDial :: new ( )
11+ . apply_rotations ( & self . parse ( input) )
12+ . stops_at_zero ( )
13+ . to_string ( )
1114 }
1215
1316 fn part_two ( & self , input : & str ) -> String {
14- self . run ( input) . points_to_zero ( ) . to_string ( )
17+ SafeDial :: new ( )
18+ . apply_rotations ( & self . parse ( input) )
19+ . points_to_zero ( )
20+ . to_string ( )
1521 }
1622}
1723
1824impl Day01 {
1925 fn parse ( & self , input : & str ) -> Vec < Rotation > {
2026 input. lines ( ) . map ( |line| line. parse ( ) . unwrap ( ) ) . collect ( )
2127 }
22-
23- fn run ( & self , input : & str ) -> SafeDial {
24- let rotations = self . parse ( input) ;
25- let mut dial = SafeDial :: new ( ) ;
26-
27- for rotation in rotations {
28- dial = dial. rotate ( rotation) ;
29- }
30-
31- dial
32- }
3328}
3429
3530struct SafeDial {
@@ -49,42 +44,56 @@ impl SafeDial {
4944 }
5045 }
5146
52- fn rotate ( & self , rotation : Rotation ) -> Self {
53- let to_apply = match rotation. direction {
54- Direction :: Left => -( rotation. distance as i16 ) ,
55- Direction :: Right => rotation. distance as i16 ,
56- } ;
57- let diff: i16 = self . position as i16 + to_apply;
47+ fn apply_rotations ( & self , rotations : & [ Rotation ] ) -> Self {
48+ rotations
49+ . iter ( )
50+ . fold ( SafeDial :: new ( ) , |acc, rotation| acc. rotate ( rotation) )
51+ }
5852
59- let mut zero_stops = self . zero_stops ;
53+ fn rotate ( & self , rotation : & Rotation ) -> Self {
54+ let position = self . new_position ( rotation) ;
55+ let zero_stops = self . new_zero_stops ( position) ;
56+ let zero_clicks = self . new_zero_clicks ( rotation) ;
6057
61- let new_position = diff. rem_euclid ( Self :: DIAL_NUMBERS_COUNT ) as u16 ;
62- if new_position == 0 {
63- zero_stops += 1 ;
58+ Self {
59+ position,
60+ zero_stops,
61+ zero_clicks,
6462 }
63+ }
6564
66- let zero_clicks = self . zero_clicks
67- + match rotation. direction {
68- Direction :: Left => {
69- let mut base = 100 - self . position + rotation. distance ;
70- if self . position == 0 {
71- base -= 100 ;
72- }
65+ fn new_position ( & self , rotation : & Rotation ) -> u16 {
66+ let diff: i16 = match rotation. direction {
67+ Direction :: Left => self . position as i16 - rotation. distance as i16 ,
68+ Direction :: Right => self . position as i16 + rotation. distance as i16 ,
69+ } ;
7370
74- base. div ( Self :: DIAL_NUMBERS_COUNT as u16 )
75- }
76- Direction :: Right => {
77- ( self . position + rotation. distance ) . div ( Self :: DIAL_NUMBERS_COUNT as u16 )
78- }
79- } ;
71+ diff. rem_euclid ( Self :: DIAL_NUMBERS_COUNT ) as u16
72+ }
8073
81- Self {
82- position : new_position,
83- zero_stops,
84- zero_clicks ,
74+ fn new_zero_stops ( & self , new_position : u16 ) -> u16 {
75+ match new_position {
76+ 0 => self . zero_stops + 1 ,
77+ _ => self . zero_stops ,
8578 }
8679 }
8780
81+ fn new_zero_clicks ( & self , rotation : & Rotation ) -> u16 {
82+ let numerator = match rotation. direction {
83+ Direction :: Right => self . position + rotation. distance ,
84+ Direction :: Left => {
85+ rotation. distance
86+ + if self . position == 0 {
87+ 0
88+ } else {
89+ 100 - self . position
90+ }
91+ }
92+ } ;
93+
94+ self . zero_clicks + numerator. div ( Self :: DIAL_NUMBERS_COUNT as u16 )
95+ }
96+
8897 fn stops_at_zero ( & self ) -> u16 {
8998 self . zero_stops
9099 }
@@ -195,43 +204,43 @@ L82"#;
195204 fn zero_stops_test ( ) {
196205 let mut dial = SafeDial :: new ( ) ;
197206
198- dial = dial. rotate ( Rotation :: left ( 68 ) ) ;
207+ dial = dial. rotate ( & Rotation :: left ( 68 ) ) ;
199208 assert_eq ! ( 82 , dial. position) ;
200209 assert_eq ! ( 0 , dial. stops_at_zero( ) ) ;
201210
202- dial = dial. rotate ( Rotation :: left ( 30 ) ) ;
211+ dial = dial. rotate ( & Rotation :: left ( 30 ) ) ;
203212 assert_eq ! ( 52 , dial. position) ;
204213 assert_eq ! ( 0 , dial. stops_at_zero( ) ) ;
205214
206- dial = dial. rotate ( Rotation :: right ( 48 ) ) ;
215+ dial = dial. rotate ( & Rotation :: right ( 48 ) ) ;
207216 assert_eq ! ( 0 , dial. position) ;
208217 assert_eq ! ( 1 , dial. stops_at_zero( ) ) ;
209218
210- dial = dial. rotate ( Rotation :: left ( 5 ) ) ;
219+ dial = dial. rotate ( & Rotation :: left ( 5 ) ) ;
211220 assert_eq ! ( 95 , dial. position) ;
212221 assert_eq ! ( 1 , dial. stops_at_zero( ) ) ;
213222
214- dial = dial. rotate ( Rotation :: right ( 60 ) ) ;
223+ dial = dial. rotate ( & Rotation :: right ( 60 ) ) ;
215224 assert_eq ! ( 55 , dial. position) ;
216225 assert_eq ! ( 1 , dial. stops_at_zero( ) ) ;
217226
218- dial = dial. rotate ( Rotation :: left ( 55 ) ) ;
227+ dial = dial. rotate ( & Rotation :: left ( 55 ) ) ;
219228 assert_eq ! ( 0 , dial. position) ;
220229 assert_eq ! ( 2 , dial. stops_at_zero( ) ) ;
221230
222- dial = dial. rotate ( Rotation :: left ( 1 ) ) ;
231+ dial = dial. rotate ( & Rotation :: left ( 1 ) ) ;
223232 assert_eq ! ( 99 , dial. position) ;
224233 assert_eq ! ( 2 , dial. stops_at_zero( ) ) ;
225234
226- dial = dial. rotate ( Rotation :: left ( 99 ) ) ;
235+ dial = dial. rotate ( & Rotation :: left ( 99 ) ) ;
227236 assert_eq ! ( 0 , dial. position) ;
228237 assert_eq ! ( 3 , dial. stops_at_zero( ) ) ;
229238
230- dial = dial. rotate ( Rotation :: right ( 14 ) ) ;
239+ dial = dial. rotate ( & Rotation :: right ( 14 ) ) ;
231240 assert_eq ! ( 14 , dial. position) ;
232241 assert_eq ! ( 3 , dial. stops_at_zero( ) ) ;
233242
234- dial = dial. rotate ( Rotation :: left ( 82 ) ) ;
243+ dial = dial. rotate ( & Rotation :: left ( 82 ) ) ;
235244 assert_eq ! ( 32 , dial. position) ;
236245 assert_eq ! ( 3 , dial. stops_at_zero( ) ) ;
237246 }
@@ -240,73 +249,73 @@ L82"#;
240249 fn position_at_zero_on_right ( ) {
241250 let mut dial = SafeDial :: new ( ) ; // 50
242251
243- dial = dial. rotate ( Rotation :: right ( 12 ) ) ; // 62
252+ dial = dial. rotate ( & Rotation :: right ( 12 ) ) ; // 62
244253 assert_eq ! ( 0 , dial. points_to_zero( ) ) ;
245254
246- dial = dial. rotate ( Rotation :: right ( 52 ) ) ; // 14
255+ dial = dial. rotate ( & Rotation :: right ( 52 ) ) ; // 14
247256 assert_eq ! ( 1 , dial. points_to_zero( ) ) ;
248257
249- dial = dial. rotate ( Rotation :: right ( 265 ) ) ; // 79
258+ dial = dial. rotate ( & Rotation :: right ( 265 ) ) ; // 79
250259 assert_eq ! ( 3 , dial. points_to_zero( ) ) ;
251260
252- dial = dial. rotate ( Rotation :: right ( 421 ) ) ; // 0
261+ dial = dial. rotate ( & Rotation :: right ( 421 ) ) ; // 0
253262 assert_eq ! ( 8 , dial. points_to_zero( ) ) ;
254263
255- dial = dial. rotate ( Rotation :: right ( 500 ) ) ; // 0
264+ dial = dial. rotate ( & Rotation :: right ( 500 ) ) ; // 0
256265 assert_eq ! ( 13 , dial. points_to_zero( ) ) ;
257266
258- dial = dial. rotate ( Rotation :: right ( 27 ) ) ; // 27
267+ dial = dial. rotate ( & Rotation :: right ( 27 ) ) ; // 27
259268 assert_eq ! ( 13 , dial. points_to_zero( ) ) ;
260269 }
261270
262271 #[ test]
263272 fn position_at_zero_on_left ( ) {
264273 let mut dial = SafeDial :: new ( ) ; // 50
265274
266- dial = dial. rotate ( Rotation :: left ( 12 ) ) ;
275+ dial = dial. rotate ( & Rotation :: left ( 12 ) ) ;
267276 assert_eq ! ( 38 , dial. position) ;
268277 assert_eq ! ( 0 , dial. points_to_zero( ) ) ;
269278
270- dial = dial. rotate ( Rotation :: left ( 99 ) ) ;
279+ dial = dial. rotate ( & Rotation :: left ( 99 ) ) ;
271280 assert_eq ! ( 39 , dial. position) ;
272281 assert_eq ! ( 1 , dial. points_to_zero( ) ) ;
273282
274283 // 1 39, 165
275284 // 2 39, 65
276285 // 3 52
277- dial = dial. rotate ( Rotation :: left ( 265 ) ) ;
286+ dial = dial. rotate ( & Rotation :: left ( 265 ) ) ;
278287 assert_eq ! ( 74 , dial. position) ;
279288 assert_eq ! ( 4 , dial. points_to_zero( ) ) ;
280289
281290 // 1 74, 89
282291 // 2 85
283- dial = dial. rotate ( Rotation :: left ( 189 ) ) ;
292+ dial = dial. rotate ( & Rotation :: left ( 189 ) ) ;
284293 assert_eq ! ( 85 , dial. position) ;
285294 assert_eq ! ( 6 , dial. points_to_zero( ) ) ;
286295
287296 // 1 85, 120
288297 // 2 85, 20
289298 // 2 65
290- dial = dial. rotate ( Rotation :: left ( 220 ) ) ;
299+ dial = dial. rotate ( & Rotation :: left ( 220 ) ) ;
291300 assert_eq ! ( 65 , dial. position) ;
292301 assert_eq ! ( 8 , dial. points_to_zero( ) ) ;
293302
294303 // 1 65, 265
295304 // 2 65, 165
296305 // 3 65, 65
297306 // 4 0
298- dial = dial. rotate ( Rotation :: left ( 365 ) ) ; // 0
307+ dial = dial. rotate ( & Rotation :: left ( 365 ) ) ; // 0
299308 assert_eq ! ( 12 , dial. points_to_zero( ) ) ;
300309
301310 // 1 0, 400
302311 // 2 0, 300
303312 // 3 0, 200
304313 // 4 0, 100
305314 // 5 0
306- dial = dial. rotate ( Rotation :: left ( 500 ) ) ; // 0
315+ dial = dial. rotate ( & Rotation :: left ( 500 ) ) ; // 0
307316 assert_eq ! ( 17 , dial. points_to_zero( ) ) ;
308317
309- dial = dial. rotate ( Rotation :: left ( 27 ) ) ; // 73
318+ dial = dial. rotate ( & Rotation :: left ( 27 ) ) ; // 73
310319 assert_eq ! ( 17 , dial. points_to_zero( ) ) ;
311320 }
312321}
0 commit comments