|
@@ -12,7 +12,9 @@ type Result<T> = result::Result<T, Box<dyn Error>>;
|
12
|
12
|
|
13
|
13
|
#[derive(Debug, Clone, PartialEq)]
|
14
|
14
|
pub struct Intcode {
|
15
|
|
- integers: Vec<i32>,
|
|
15
|
+ pub integers: Vec<i32>,
|
|
16
|
+ pub pointer: usize,
|
|
17
|
+ pub halted: bool,
|
16
|
18
|
}
|
17
|
19
|
|
18
|
20
|
#[derive(Debug, PartialEq)]
|
|
@@ -105,16 +107,23 @@ impl FromStr for Intcode {
|
105
|
107
|
fn from_str(s: &str) -> Result<Intcode> {
|
106
|
108
|
let intcode_string = s.trim().to_string();
|
107
|
109
|
|
108
|
|
- Ok(Intcode {
|
109
|
|
- integers: intcode_string
|
|
110
|
+ Ok(Intcode::new(
|
|
111
|
+ intcode_string
|
110
|
112
|
.split(',')
|
111
|
113
|
.map(|code| code.parse().unwrap())
|
112
|
114
|
.collect(),
|
113
|
|
- })
|
|
115
|
+ ))
|
114
|
116
|
}
|
115
|
117
|
}
|
116
|
118
|
|
117
|
119
|
impl Intcode {
|
|
120
|
+ fn new(integers: Vec<i32>) -> Intcode {
|
|
121
|
+ Intcode {
|
|
122
|
+ integers,
|
|
123
|
+ pointer: 0,
|
|
124
|
+ halted: false,
|
|
125
|
+ }
|
|
126
|
+ }
|
118
|
127
|
fn load_parameters(&self, pointer: usize, instruction: &Instruction) -> Vec<i32> {
|
119
|
128
|
(0..instruction.opcode.parameter_count() as usize)
|
120
|
129
|
.map(|parameter_index| {
|
|
@@ -134,13 +143,12 @@ impl Intcode {
|
134
|
143
|
}
|
135
|
144
|
|
136
|
145
|
pub fn execute(&mut self, inputs: &[i32]) -> Result<Vec<i32>> {
|
137
|
|
- let mut pointer = 0;
|
138
|
146
|
let mut input_index = 0;
|
139
|
147
|
let mut output = vec![];
|
140
|
148
|
|
141
|
149
|
loop {
|
142
|
|
- let instruction = Instruction::try_from(self.integers[pointer])?;
|
143
|
|
- let parameters = self.load_parameters(pointer, &instruction);
|
|
150
|
+ let instruction = Instruction::try_from(self.integers[self.pointer])?;
|
|
151
|
+ let parameters = self.load_parameters(self.pointer, &instruction);
|
144
|
152
|
let mut jump_pointer: Option<usize> = None;
|
145
|
153
|
|
146
|
154
|
match instruction.opcode {
|
|
@@ -151,6 +159,9 @@ impl Intcode {
|
151
|
159
|
self.integers[parameters[2] as usize] = parameters[0] * parameters[1];
|
152
|
160
|
}
|
153
|
161
|
Opcode::Input => {
|
|
162
|
+ if input_index >= inputs.len() {
|
|
163
|
+ break; // pause execution to wait for more input
|
|
164
|
+ }
|
154
|
165
|
self.integers[parameters[0] as usize] = inputs[input_index];
|
155
|
166
|
input_index += 1;
|
156
|
167
|
}
|
|
@@ -182,13 +193,14 @@ impl Intcode {
|
182
|
193
|
}
|
183
|
194
|
}
|
184
|
195
|
Opcode::Halt => {
|
|
196
|
+ self.halted = true;
|
185
|
197
|
break;
|
186
|
198
|
}
|
187
|
199
|
}
|
188
|
200
|
|
189
|
201
|
match jump_pointer {
|
190
|
|
- Some(jump_pointer) => pointer = jump_pointer,
|
191
|
|
- None => pointer += 1 + instruction.opcode.parameter_count() as usize,
|
|
202
|
+ Some(jump_pointer) => self.pointer = jump_pointer,
|
|
203
|
+ None => self.pointer += 1 + instruction.opcode.parameter_count() as usize,
|
192
|
204
|
}
|
193
|
205
|
}
|
194
|
206
|
|
|
@@ -214,9 +226,7 @@ mod tests {
|
214
|
226
|
fn reads_intcode() {
|
215
|
227
|
assert_eq!(
|
216
|
228
|
read_intcode(TEST_INPUT).unwrap(),
|
217
|
|
- Intcode {
|
218
|
|
- integers: vec![3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0]
|
219
|
|
- },
|
|
229
|
+ Intcode::new(vec![3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0]),
|
220
|
230
|
);
|
221
|
231
|
}
|
222
|
232
|
|
|
@@ -249,33 +259,23 @@ mod tests {
|
249
|
259
|
|
250
|
260
|
#[test]
|
251
|
261
|
fn executes_intcodes() {
|
252
|
|
- let mut intcode = Intcode {
|
253
|
|
- integers: vec![1, 0, 0, 0, 99],
|
254
|
|
- };
|
|
262
|
+ let mut intcode = Intcode::new(vec![1, 0, 0, 0, 99]);
|
255
|
263
|
intcode.execute(&[0]).unwrap();
|
256
|
264
|
assert_eq!(intcode.integers, vec![2, 0, 0, 0, 99]);
|
257
|
265
|
|
258
|
|
- let mut intcode = Intcode {
|
259
|
|
- integers: vec![2, 3, 0, 3, 99],
|
260
|
|
- };
|
|
266
|
+ let mut intcode = Intcode::new(vec![2, 3, 0, 3, 99]);
|
261
|
267
|
intcode.execute(&[0]).unwrap();
|
262
|
268
|
assert_eq!(intcode.integers, vec![2, 3, 0, 6, 99]);
|
263
|
269
|
|
264
|
|
- let mut intcode = Intcode {
|
265
|
|
- integers: vec![2, 4, 4, 5, 99, 0],
|
266
|
|
- };
|
|
270
|
+ let mut intcode = Intcode::new(vec![2, 4, 4, 5, 99, 0]);
|
267
|
271
|
intcode.execute(&[0]).unwrap();
|
268
|
272
|
assert_eq!(intcode.integers, vec![2, 4, 4, 5, 99, 9801]);
|
269
|
273
|
|
270
|
|
- let mut intcode = Intcode {
|
271
|
|
- integers: vec![1, 1, 1, 4, 99, 5, 6, 0, 99],
|
272
|
|
- };
|
|
274
|
+ let mut intcode = Intcode::new(vec![1, 1, 1, 4, 99, 5, 6, 0, 99]);
|
273
|
275
|
intcode.execute(&[0]).unwrap();
|
274
|
276
|
assert_eq!(intcode.integers, vec![30, 1, 1, 4, 2, 5, 6, 0, 99]);
|
275
|
277
|
|
276
|
|
- let mut intcode = Intcode {
|
277
|
|
- integers: vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50],
|
278
|
|
- };
|
|
278
|
+ let mut intcode = Intcode::new(vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]);
|
279
|
279
|
intcode.execute(&[0]).unwrap();
|
280
|
280
|
assert_eq!(
|
281
|
281
|
intcode.integers,
|
|
@@ -285,55 +285,41 @@ mod tests {
|
285
|
285
|
|
286
|
286
|
#[test]
|
287
|
287
|
fn less_and_equal_outputs() {
|
288
|
|
- let intcode = Intcode {
|
289
|
|
- integers: vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8],
|
290
|
|
- };
|
|
288
|
+ let intcode = Intcode::new(vec![3, 9, 8, 9, 10, 9, 4, 9, 99, -1, 8]);
|
291
|
289
|
assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1]);
|
292
|
290
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]);
|
293
|
291
|
|
294
|
|
- let intcode = Intcode {
|
295
|
|
- integers: vec![3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8],
|
296
|
|
- };
|
|
292
|
+ let intcode = Intcode::new(vec![3, 9, 7, 9, 10, 9, 4, 9, 99, -1, 8]);
|
297
|
293
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![1]);
|
298
|
294
|
assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![0]);
|
299
|
295
|
|
300
|
|
- let intcode = Intcode {
|
301
|
|
- integers: vec![3, 3, 1108, -1, 8, 3, 4, 3, 99],
|
302
|
|
- };
|
|
296
|
+ let intcode = Intcode::new(vec![3, 3, 1108, -1, 8, 3, 4, 3, 99]);
|
303
|
297
|
assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1]);
|
304
|
298
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]);
|
305
|
299
|
|
306
|
|
- let intcode = Intcode {
|
307
|
|
- integers: vec![3, 3, 1107, -1, 8, 3, 4, 3, 99],
|
308
|
|
- };
|
|
300
|
+ let intcode = Intcode::new(vec![3, 3, 1107, -1, 8, 3, 4, 3, 99]);
|
309
|
301
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![1]);
|
310
|
302
|
assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![0]);
|
311
|
303
|
}
|
312
|
304
|
|
313
|
305
|
#[test]
|
314
|
306
|
fn jump_outputs() {
|
315
|
|
- let intcode = Intcode {
|
316
|
|
- integers: vec![3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9],
|
317
|
|
- };
|
|
307
|
+ let intcode = Intcode::new(vec![3, 12, 6, 12, 15, 1, 13, 14, 13, 4, 13, 99, -1, 0, 1, 9]);
|
318
|
308
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]);
|
319
|
309
|
assert_eq!(intcode.clone().execute(&[1]).unwrap(), vec![1]);
|
320
|
310
|
|
321
|
|
- let intcode = Intcode {
|
322
|
|
- integers: vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1],
|
323
|
|
- };
|
|
311
|
+ let intcode = Intcode::new(vec![3, 3, 1105, -1, 9, 1101, 0, 0, 12, 4, 12, 99, 1]);
|
324
|
312
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![0]);
|
325
|
313
|
assert_eq!(intcode.clone().execute(&[1]).unwrap(), vec![1]);
|
326
|
314
|
}
|
327
|
315
|
|
328
|
316
|
#[test]
|
329
|
317
|
fn larger_part2_intcode() {
|
330
|
|
- let intcode = Intcode {
|
331
|
|
- integers: vec![
|
|
318
|
+ let intcode = Intcode::new(vec![
|
332
|
319
|
3, 21, 1008, 21, 8, 20, 1005, 20, 22, 107, 8, 21, 20, 1006, 20, 31, 1106, 0, 36,
|
333
|
320
|
98, 0, 0, 1002, 21, 125, 20, 4, 20, 1105, 1, 46, 104, 999, 1105, 1, 46, 1101, 1000,
|
334
|
321
|
1, 20, 4, 20, 1105, 1, 46, 98, 99,
|
335
|
|
- ],
|
336
|
|
- };
|
|
322
|
+ ]);
|
337
|
323
|
assert_eq!(intcode.clone().execute(&[0]).unwrap(), vec![999]);
|
338
|
324
|
assert_eq!(intcode.clone().execute(&[8]).unwrap(), vec![1000]);
|
339
|
325
|
assert_eq!(intcode.clone().execute(&[9]).unwrap(), vec![1001]);
|
|
@@ -341,11 +327,9 @@ mod tests {
|
341
|
327
|
|
342
|
328
|
#[test]
|
343
|
329
|
fn multiple_input_intcode() {
|
344
|
|
- let intcode = Intcode {
|
345
|
|
- integers: vec![
|
|
330
|
+ let intcode = Intcode::new(vec![
|
346
|
331
|
3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0,
|
347
|
|
- ],
|
348
|
|
- };
|
|
332
|
+ ]);
|
349
|
333
|
assert_eq!(intcode.clone().execute(&[1, 1]).unwrap(), vec![11]);
|
350
|
334
|
}
|
351
|
335
|
}
|