this repo has no description
1use std::fs;
2
3type IntCodes = Vec<isize>;
4
5#[derive(Clone)]
6struct IntCodeComp {
7 pos: usize,
8 rel_base: isize,
9 codes: IntCodes,
10 inputs: Vec<isize>,
11 done: bool,
12}
13
14impl IntCodeComp {
15 fn new(codes: IntCodes, rel_base: isize, inputs: Vec<isize>) -> IntCodeComp {
16 IntCodeComp{ codes, inputs, rel_base, pos: 0, done: false }
17 }
18
19 fn val_param(&mut self, t: char, v: isize) -> isize {
20 match t {
21 '0' => { // Position mode
22 self.grow(v as usize);
23 return self.codes[v as usize];
24 },
25 '1' => { // Absolute mode
26 return v;
27 },
28 '2' => { // Relative mode
29 let dest = (self.rel_base + v) as usize;
30 self.grow(dest);
31 return self.codes[dest];
32 },
33 _ => unreachable!(),
34 }
35 }
36
37 fn write_param(&self, opcode: String, idx: usize) -> isize {
38 let param_type = opcode.chars().nth(4-idx).unwrap();
39 let v = self.codes[self.pos+idx];
40
41 match param_type {
42 '0' | '1' => v,
43 '2' => self.rel_base + v,
44 _ => unreachable!(),
45 }
46 }
47
48 fn n_params(&mut self, opcode: String, num: usize) -> Vec<isize> {
49 let out = (1..=num).fold(vec![], |mut out, i| {
50 let param_type = opcode.chars().nth(4-i).unwrap();
51 let param = self.val_param(param_type, self.codes[self.pos+i]);
52 out.push(param);
53 out.clone()
54 });
55 out
56 }
57
58 fn grow(&mut self, pos: usize) {
59 while self.codes.len() < pos+1 {
60 self.codes.push(0);
61 }
62 }
63
64 fn set_val(&mut self, dest: isize, val: isize) {
65 self.grow(dest as usize);
66 self.codes[dest as usize] = val;
67 }
68
69 fn set_pos(&mut self, dest: isize) {
70 self.grow(dest as usize);
71 self.pos = dest as usize;
72 }
73
74 fn advance_pos(&mut self, offset: usize) {
75 let new_pos = self.pos + offset;
76 self.grow(new_pos);
77 self.pos = new_pos;
78 }
79}
80
81impl Iterator for IntCodeComp {
82 type Item = isize;
83
84 fn next(&mut self) -> Option<Self::Item> {
85 if self.done { return None; }
86 loop {
87 if self.codes[self.pos] == 99 { return None; }
88
89 let opcode = format!("{:0>6}", self.codes[self.pos]);
90 match opcode.chars().nth(5) {
91 Some('1') => { // Add
92 let params = self.n_params(opcode.clone(), 2);
93 let dest = self.write_param(opcode.clone(), 3);
94 self.set_val(dest, params[0] + params[1]);
95 self.advance_pos(4);
96 },
97 Some('2') => { // Mult
98 let params = self.n_params(opcode.clone(), 2);
99 let dest = self.write_param(opcode.clone(), 3);
100 self.set_val(dest, params[0] * params[1]);
101 self.advance_pos(4);
102 },
103 Some('3') => { // Input
104 let dest = self.write_param(opcode.clone(), 3);
105 let v = match self.inputs.pop() {
106 Some(i) => i,
107 None => return None,
108 };
109 self.set_val(dest, v);
110 self.advance_pos(2);
111 },
112 Some('4') => { // Output
113 let x = *self.n_params(opcode, 1).first().unwrap();
114 self.advance_pos(2);
115 return Some(x);
116 },
117 Some('5') => { // Jump If True
118 let params = self.n_params(opcode, 2);
119 if params[0] > 0 {
120 self.set_pos(params[1]);
121 } else {
122 self.advance_pos(3);
123 }
124 },
125 Some('6') => { // Jump If False
126 let params = self.n_params(opcode, 2);
127 if params[0] == 0 {
128 self.set_pos(params[1]);
129 } else {
130 self.advance_pos(3);
131 }
132 },
133 Some('7') => { // Less Than
134 let params = self.n_params(opcode.clone(), 2);
135 let dest = self.write_param(opcode.clone(), 3);
136 if params[0] < params[1] {
137 self.set_val(dest, 1);
138 } else {
139 self.set_val(dest, 0);
140 }
141 self.advance_pos(4);
142 },
143 Some('8') => { // Equals
144 let params = self.n_params(opcode.clone(), 2);
145 let dest = self.write_param(opcode.clone(), 3);
146 if params[0] == params[1] {
147 self.set_val(dest, 1);
148 } else {
149 self.set_val(dest, 0);
150 }
151 self.advance_pos(4);
152 },
153 Some('9') => { // Relative Base Offset
154 let params = self.n_params(opcode, 1);
155 self.rel_base += params[0];
156 self.advance_pos(2);
157 },
158 Some(_) => return None,
159 None => return None,
160 }
161 }
162 }
163}
164
165fn main() {
166 let raw_contents = fs::read_to_string("input.txt").expect("Error reading the file.");
167 let contents = raw_contents.trim(); // get rid of trailing \n
168
169 let intcodes: IntCodes = contents.split(',').map(|x| x.parse().unwrap()).collect();
170
171 // let comp = IntCodeComp::new(intcodes.clone(), 0, vec![2]); // Part 1
172 let comp = IntCodeComp::new(intcodes.clone(), 0, vec![2]); // Part 2
173
174 comp.for_each(|out| println!("{}", out));
175}