|
@@ -11,7 +11,7 @@ const INPUT: &str = "input/input.txt";
|
11
|
11
|
|
12
|
12
|
type Result<T> = result::Result<T, Box<dyn Error>>;
|
13
|
13
|
|
14
|
|
-#[derive(Debug, PartialEq)]
|
|
14
|
+#[derive(Debug, Clone, PartialEq)]
|
15
|
15
|
struct Intcode {
|
16
|
16
|
integers: Vec<i32>,
|
17
|
17
|
}
|
|
@@ -56,6 +56,10 @@ enum Opcode {
|
56
|
56
|
Mult = 2,
|
57
|
57
|
Input = 3,
|
58
|
58
|
Output = 4,
|
|
59
|
+ JumpIfTrue = 5,
|
|
60
|
+ JumpIfFalse = 6,
|
|
61
|
+ LessThan = 7,
|
|
62
|
+ Equals = 8,
|
59
|
63
|
Halt = 99,
|
60
|
64
|
}
|
61
|
65
|
|
|
@@ -66,6 +70,10 @@ impl Opcode {
|
66
|
70
|
Opcode::Mult => 3,
|
67
|
71
|
Opcode::Input => 1,
|
68
|
72
|
Opcode::Output => 1,
|
|
73
|
+ Opcode::JumpIfTrue => 2,
|
|
74
|
+ Opcode::JumpIfFalse => 2,
|
|
75
|
+ Opcode::LessThan => 3,
|
|
76
|
+ Opcode::Equals => 3,
|
69
|
77
|
Opcode::Halt => 0,
|
70
|
78
|
}
|
71
|
79
|
}
|
|
@@ -76,6 +84,10 @@ impl Opcode {
|
76
|
84
|
Opcode::Mult => Some(2),
|
77
|
85
|
Opcode::Input => Some(0),
|
78
|
86
|
Opcode::Output => None,
|
|
87
|
+ Opcode::JumpIfTrue => None,
|
|
88
|
+ Opcode::JumpIfFalse => None,
|
|
89
|
+ Opcode::LessThan => Some(2),
|
|
90
|
+ Opcode::Equals => Some(2),
|
79
|
91
|
Opcode::Halt => None,
|
80
|
92
|
}
|
81
|
93
|
}
|
|
@@ -129,6 +141,7 @@ impl Intcode {
|
129
|
141
|
loop {
|
130
|
142
|
let instruction = Instruction::try_from(self.integers[pointer])?;
|
131
|
143
|
let parameters = self.load_parameters(pointer, &instruction);
|
|
144
|
+ let mut jump_pointer: Option<usize> = None;
|
132
|
145
|
|
133
|
146
|
match instruction.opcode {
|
134
|
147
|
Opcode::Add => {
|
|
@@ -143,12 +156,39 @@ impl Intcode {
|
143
|
156
|
Opcode::Output => {
|
144
|
157
|
output.push(parameters[0]);
|
145
|
158
|
}
|
|
159
|
+ Opcode::JumpIfTrue => {
|
|
160
|
+ if parameters[0] != 0 {
|
|
161
|
+ jump_pointer = Some(parameters[1] as usize);
|
|
162
|
+ }
|
|
163
|
+ }
|
|
164
|
+ Opcode::JumpIfFalse => {
|
|
165
|
+ if parameters[0] == 0 {
|
|
166
|
+ jump_pointer = Some(parameters[1] as usize);
|
|
167
|
+ }
|
|
168
|
+ }
|
|
169
|
+ Opcode::LessThan => {
|
|
170
|
+ if parameters[0] < parameters[1] {
|
|
171
|
+ self.integers[parameters[2] as usize] = 1;
|
|
172
|
+ } else {
|
|
173
|
+ self.integers[parameters[2] as usize] = 0;
|
|
174
|
+ }
|
|
175
|
+ }
|
|
176
|
+ Opcode::Equals => {
|
|
177
|
+ if parameters[0] == parameters[1] {
|
|
178
|
+ self.integers[parameters[2] as usize] = 1;
|
|
179
|
+ } else {
|
|
180
|
+ self.integers[parameters[2] as usize] = 0;
|
|
181
|
+ }
|
|
182
|
+ }
|
146
|
183
|
Opcode::Halt => {
|
147
|
184
|
break;
|
148
|
185
|
}
|
149
|
186
|
}
|
150
|
187
|
|
151
|
|
- pointer += 1 + instruction.opcode.parameter_count() as usize;
|
|
188
|
+ match jump_pointer {
|
|
189
|
+ Some(jump_pointer) => pointer = jump_pointer,
|
|
190
|
+ None => pointer += 1 + instruction.opcode.parameter_count() as usize,
|
|
191
|
+ }
|
152
|
192
|
}
|
153
|
193
|
|
154
|
194
|
Ok(output)
|
|
@@ -168,12 +208,14 @@ fn solve_part1() -> Result<i32> {
|
168
|
208
|
Ok(intcode.execute(1)?.into_iter().last().ok_or("No output")?)
|
169
|
209
|
}
|
170
|
210
|
|
171
|
|
-// fn solve_part2() -> io::Result<i32> {
|
172
|
|
-// }
|
|
211
|
+fn solve_part2() -> Result<i32> {
|
|
212
|
+ let mut intcode = read_intcode(INPUT)?;
|
|
213
|
+ Ok(intcode.execute(5)?.into_iter().last().ok_or("No output")?)
|
|
214
|
+}
|
173
|
215
|
|
174
|
216
|
fn main() -> Result<()> {
|
175
|
|
- println!("Part 1: {:?}", solve_part1()?);
|
176
|
|
- // println!("Part 2: {}", solve_part2()?);
|
|
217
|
+ println!("Part 1: {}", solve_part1()?);
|
|
218
|
+ println!("Part 2: {}", solve_part2()?);
|
177
|
219
|
|
178
|
220
|
Ok(())
|
179
|
221
|
}
|
|
@@ -256,4 +298,60 @@ mod tests {
|
256
|
298
|
vec![3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50]
|
257
|
299
|
);
|
258
|
300
|
}
|
|
301
|
+
|
|
302
|
+ #[test]
|
|
303
|
+ fn less_and_equal_outputs() {
|
|
304
|
+ let intcode = Intcode {
|
|
305
|
+ integers: vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8],
|
|
306
|
+ };
|
|
307
|
+ assert_eq!(intcode.clone().execute(8).unwrap(), vec![1]);
|
|
308
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![0]);
|
|
309
|
+
|
|
310
|
+ let intcode = Intcode {
|
|
311
|
+ integers: vec![3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8],
|
|
312
|
+ };
|
|
313
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![1]);
|
|
314
|
+ assert_eq!(intcode.clone().execute(9).unwrap(), vec![0]);
|
|
315
|
+
|
|
316
|
+ let intcode = Intcode {
|
|
317
|
+ integers: vec![3, 3, 1108, -1, 8, 3, 4, 3, 99],
|
|
318
|
+ };
|
|
319
|
+ assert_eq!(intcode.clone().execute(8).unwrap(), vec![1]);
|
|
320
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![0]);
|
|
321
|
+
|
|
322
|
+ let intcode = Intcode {
|
|
323
|
+ integers: vec![3, 3, 1107, -1, 8, 3, 4, 3, 99],
|
|
324
|
+ };
|
|
325
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![1]);
|
|
326
|
+ assert_eq!(intcode.clone().execute(9).unwrap(), vec![0]);
|
|
327
|
+ }
|
|
328
|
+
|
|
329
|
+ #[test]
|
|
330
|
+ fn jump_outputs() {
|
|
331
|
+ let intcode = Intcode {
|
|
332
|
+ integers: vec![3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9],
|
|
333
|
+ };
|
|
334
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![0]);
|
|
335
|
+ assert_eq!(intcode.clone().execute(1).unwrap(), vec![1]);
|
|
336
|
+
|
|
337
|
+ let intcode = Intcode {
|
|
338
|
+ integers: vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1],
|
|
339
|
+ };
|
|
340
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![0]);
|
|
341
|
+ assert_eq!(intcode.clone().execute(1).unwrap(), vec![1]);
|
|
342
|
+ }
|
|
343
|
+
|
|
344
|
+ #[test]
|
|
345
|
+ fn larger_part2_intcode() {
|
|
346
|
+ let intcode = Intcode {
|
|
347
|
+ integers: vec![
|
|
348
|
+ 3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36,
|
|
349
|
+ 98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000,
|
|
350
|
+ 1, 20, 4, 20, 1105, 1, 46, 98, 99,
|
|
351
|
+ ],
|
|
352
|
+ };
|
|
353
|
+ assert_eq!(intcode.clone().execute(0).unwrap(), vec![999]);
|
|
354
|
+ assert_eq!(intcode.clone().execute(8).unwrap(), vec![1000]);
|
|
355
|
+ assert_eq!(intcode.clone().execute(9).unwrap(), vec![1001]);
|
|
356
|
+ }
|
259
|
357
|
}
|