1
1
use std:: io:: Result ;
2
2
3
- use crate :: Input ;
3
+ use crate :: { instruction :: Instruction , instruction :: Operation :: * , Input } ;
4
4
5
- pub fn main ( _input : & Input ) -> Result < ( ) > {
6
- Ok ( ( ) )
5
+ #[ derive( Default , Debug , Eq , PartialEq , Clone ) ]
6
+ struct Program {
7
+ instructions : Vec < ( bool , Instruction ) > ,
8
+ original : Vec < Instruction > ,
9
+ accumulator : i64 ,
10
+ index : usize ,
11
+ change : usize ,
12
+ }
13
+
14
+ impl Program {
15
+ fn new ( input : & Input ) -> Self {
16
+ Self {
17
+ original : input. to_owned ( ) ,
18
+ ..Program :: default ( )
19
+ }
20
+ }
21
+
22
+ fn fix ( & mut self ) {
23
+ let mut to_change = self . change . to_owned ( ) ;
24
+ let len = self . original . len ( ) ;
25
+
26
+ self . accumulator = 0 ;
27
+ self . index = 0 ;
28
+
29
+ self . instructions = self
30
+ . original
31
+ . iter ( )
32
+ . enumerate ( )
33
+ . map ( |( index, instruction) | {
34
+ if to_change != index {
35
+ return ( false , instruction. to_owned ( ) ) ;
36
+ }
37
+
38
+ let operation = instruction. operation ;
39
+ let argument = instruction. argument ;
40
+
41
+ match operation {
42
+ ACC => {
43
+ to_change += 1 ;
44
+ ( false , instruction. to_owned ( ) )
45
+ }
46
+ NOP => (
47
+ false ,
48
+ Instruction {
49
+ operation : JMP ,
50
+ argument,
51
+ } ,
52
+ ) ,
53
+ JMP => (
54
+ false ,
55
+ Instruction {
56
+ operation : NOP ,
57
+ argument,
58
+ } ,
59
+ ) ,
60
+ }
61
+ } )
62
+ . collect :: < Vec < _ > > ( ) ;
63
+
64
+ self . change = to_change + 1 % len;
65
+ }
66
+
67
+ fn run ( mut self ) -> i64 {
68
+ let len = self . original . len ( ) as i64 ;
69
+ let next = |curr : usize , next : & i64 | -> usize {
70
+ let next_index = curr as i64 + next;
71
+ ( if next_index > len {
72
+ len - next_index
73
+ } else {
74
+ next_index
75
+ } % len) as usize
76
+ } ;
77
+
78
+ ' main: loop {
79
+ self . fix ( ) ;
80
+
81
+ ' test: loop {
82
+ let ( visited, instruction) = self . instructions . get_mut ( self . index ) . unwrap ( ) ;
83
+ if * visited {
84
+ break ' test;
85
+ }
86
+
87
+ let argument = & instruction. argument ;
88
+ let operation = instruction. operation ;
89
+ let next = next ( self . index , if operation == JMP { argument } else { & 1 } ) ;
90
+
91
+ if operation == ACC {
92
+ self . accumulator += argument;
93
+ }
94
+
95
+ if self . index != 0 && next == 0 {
96
+ break ' main;
97
+ }
98
+
99
+ * visited = true ;
100
+ self . index = next;
101
+ }
102
+ }
103
+
104
+ self . accumulator
105
+ }
106
+ }
107
+
108
+ pub fn main ( input : & Input ) -> Result < i64 > {
109
+ Ok ( Program :: new ( input) . run ( ) )
7
110
}
8
111
9
112
#[ cfg( test) ]
@@ -26,7 +129,7 @@ mod tests {
26
129
27
130
#[ test]
28
131
fn it_gets_the_example_correct ( ) -> Result < ( ) > {
29
- assert_eq ! ( main( & parse_input( & EXAMPLE_DATA ) ) ?, ( ) ) ;
132
+ assert_eq ! ( main( & parse_input( & EXAMPLE_DATA ) ) ?, 8 ) ;
30
133
Ok ( ( ) )
31
134
}
32
135
}
0 commit comments