@@ -12,8 +12,19 @@ impl Solution for Day17 {
12
12
program. execute ( & mut register) . iter ( ) . join ( "," )
13
13
}
14
14
15
- fn part_two ( & self , _input : & str ) -> String {
16
- String :: from ( "0" )
15
+ fn part_two ( & self , input : & str ) -> String {
16
+ let ( _, program) = self . parse ( input) ;
17
+
18
+ let mut i = 0 ;
19
+ loop {
20
+ let mut register = RegisterBuilder :: default ( ) . a ( i) . build ( ) ;
21
+
22
+ if program. execute_and_watch ( & mut register) {
23
+ return i. to_string ( ) ;
24
+ }
25
+
26
+ i += 1 ;
27
+ }
17
28
}
18
29
}
19
30
@@ -65,60 +76,102 @@ struct Program {
65
76
}
66
77
67
78
impl Program {
68
- fn execute ( & self , register : & mut Register ) -> Vec < usize > {
79
+ fn execute ( & self , register : & mut Register ) -> Vec < u8 > {
69
80
let mut instruction_pointer = 0 ;
70
81
let mut output = Vec :: new ( ) ;
71
82
72
83
while let Some ( [ opcode, operand] ) = self
73
84
. program
74
85
. get ( instruction_pointer..=instruction_pointer + 1 )
75
86
{
76
- let operation = InstructionType :: from ( * opcode) ;
77
- let mut do_jump = true ;
87
+ self . operation (
88
+ opcode,
89
+ operand,
90
+ register,
91
+ & mut instruction_pointer,
92
+ & mut output,
93
+ ) ;
94
+ }
78
95
79
- match operation {
80
- Adv => {
81
- let combo_operand = self . combo_operand ( operand, register) ;
82
- register. a /= 2usize . pow ( combo_operand as u32 ) ;
83
- }
84
- Bdv => {
85
- let combo_operand = self . combo_operand ( operand, register) ;
86
- register. b = register. a / 2usize . pow ( combo_operand as u32 ) ;
87
- }
88
- Cdv => {
89
- let combo_operand = self . combo_operand ( operand, register) ;
90
- register. c = register. a / 2usize . pow ( combo_operand as u32 ) ;
91
- }
92
- Bxl => {
93
- let operand_usize = * operand as usize ;
94
- register. b ^= operand_usize;
95
- }
96
- Bst => {
97
- let combo_operand = self . combo_operand ( operand, register) ;
98
- register. b = combo_operand % 8 ;
99
- }
100
- Bxc => {
101
- register. b ^= register. c ;
102
- }
103
- Jnz => {
104
- let operand_usize = * operand as usize ;
105
- if register. a != 0 && instruction_pointer != operand_usize {
106
- instruction_pointer = operand_usize;
107
- do_jump = false ;
108
- }
109
- }
110
- Out => {
111
- let combo_operand = self . combo_operand ( operand, register) ;
112
- output. push ( combo_operand % 8 ) ;
113
- }
96
+ output
97
+ }
98
+
99
+ fn execute_and_watch ( & self , register : & mut Register ) -> bool {
100
+ let mut instruction_pointer = 0 ;
101
+ let mut output = Vec :: new ( ) ;
102
+ let expected = self . program . clone ( ) ;
103
+
104
+ while let Some ( [ opcode, operand] ) = self
105
+ . program
106
+ . get ( instruction_pointer..=instruction_pointer + 1 )
107
+ {
108
+ self . operation (
109
+ opcode,
110
+ operand,
111
+ register,
112
+ & mut instruction_pointer,
113
+ & mut output,
114
+ ) ;
115
+
116
+ if expected == output {
117
+ return true ;
114
118
}
119
+ }
120
+
121
+ false
122
+ }
115
123
116
- if do_jump {
117
- instruction_pointer += 2 ;
124
+ fn operation (
125
+ & self ,
126
+ opcode : & u8 ,
127
+ operand : & u8 ,
128
+ register : & mut Register ,
129
+ instruction_pointer : & mut usize ,
130
+ output : & mut Vec < u8 > ,
131
+ ) {
132
+ let operation = InstructionType :: from ( * opcode) ;
133
+ let mut do_jump = true ;
134
+
135
+ match operation {
136
+ Adv => {
137
+ let combo_operand = self . combo_operand ( operand, register) ;
138
+ register. a /= 2usize . pow ( combo_operand as u32 ) ;
139
+ }
140
+ Bdv => {
141
+ let combo_operand = self . combo_operand ( operand, register) ;
142
+ register. b = register. a / 2usize . pow ( combo_operand as u32 ) ;
143
+ }
144
+ Cdv => {
145
+ let combo_operand = self . combo_operand ( operand, register) ;
146
+ register. c = register. a / 2usize . pow ( combo_operand as u32 ) ;
147
+ }
148
+ Bxl => {
149
+ let operand_usize = * operand as usize ;
150
+ register. b ^= operand_usize;
151
+ }
152
+ Bst => {
153
+ let combo_operand = self . combo_operand ( operand, register) ;
154
+ register. b = combo_operand % 8 ;
155
+ }
156
+ Bxc => {
157
+ register. b ^= register. c ;
158
+ }
159
+ Jnz => {
160
+ let operand_usize = * operand as usize ;
161
+ if register. a != 0 && * instruction_pointer != operand_usize {
162
+ * instruction_pointer = operand_usize;
163
+ do_jump = false ;
164
+ }
165
+ }
166
+ Out => {
167
+ let combo_operand = self . combo_operand ( operand, register) ;
168
+ output. push ( ( combo_operand % 8 ) as u8 ) ;
118
169
}
119
170
}
120
171
121
- output
172
+ if do_jump {
173
+ * instruction_pointer += 2 ;
174
+ }
122
175
}
123
176
124
177
fn combo_operand ( & self , operand : & u8 , register : & Register ) -> usize {
@@ -173,9 +226,31 @@ impl From<u8> for InstructionType {
173
226
}
174
227
}
175
228
229
+ #[ derive( Default ) ]
230
+ struct RegisterBuilder {
231
+ a : usize ,
232
+ b : usize ,
233
+ c : usize ,
234
+ }
235
+
236
+ impl RegisterBuilder {
237
+ fn a ( & mut self , a : usize ) -> & mut Self {
238
+ self . a = a;
239
+ self
240
+ }
241
+
242
+ fn build ( & self ) -> Register {
243
+ Register {
244
+ a : self . a ,
245
+ b : self . b ,
246
+ c : self . c ,
247
+ }
248
+ }
249
+ }
250
+
176
251
#[ cfg( test) ]
177
252
mod tests {
178
- use crate :: solutions:: year2024:: day17:: { Day17 , Program , Register } ;
253
+ use crate :: solutions:: year2024:: day17:: { Day17 , Program , RegisterBuilder } ;
179
254
use crate :: solutions:: Solution ;
180
255
181
256
const EXAMPLE : & str = r#"Register A: 729
@@ -267,19 +342,18 @@ Program: 0,1,5,4,3,0"#;
267
342
assert ! ( result. is_empty( ) )
268
343
}
269
344
270
- #[ derive( Default ) ]
271
- struct RegisterBuilder {
272
- a : usize ,
273
- b : usize ,
274
- c : usize ,
345
+ const EXAMPLE_PART_TWO : & str = r#"Register A: 2024
346
+ Register B: 0
347
+ Register C: 0
348
+
349
+ Program: 0,3,5,4,3,0"# ;
350
+
351
+ #[ test]
352
+ fn part_two_example ( ) {
353
+ assert_eq ! ( "117440" , Day17 . part_two( EXAMPLE_PART_TWO ) ) ;
275
354
}
276
355
277
356
impl RegisterBuilder {
278
- fn a ( & mut self , a : usize ) -> & mut Self {
279
- self . a = a;
280
- self
281
- }
282
-
283
357
fn b ( & mut self , b : usize ) -> & mut Self {
284
358
self . b = b;
285
359
self
@@ -289,13 +363,5 @@ Program: 0,1,5,4,3,0"#;
289
363
self . c = c;
290
364
self
291
365
}
292
-
293
- fn build ( & self ) -> Register {
294
- Register {
295
- a : self . a ,
296
- b : self . b ,
297
- c : self . c ,
298
- }
299
- }
300
366
}
301
367
}
0 commit comments