-fn read_code(code: i32) -> (i32, Vec<bool>) {\r
+// 'true' -> immediate mode, 'false' -> position mode.\r
+fn read_op_and_modes(mut code: i32) -> (i32, [bool; 3]) {\r
+ let mut modes: [bool; 3] = [ false, false, false ];\r
\r
+ if code >= 10_000 {\r
+ modes[2] = true;\r
+ code -= 10_000;\r
+ }\r
+\r
+ if code >= 1_000 {\r
+ modes[1] = true;\r
+ code -= 1_000;\r
+ }\r
+\r
+ if code >= 100 {\r
+ modes[0] = true;\r
+ code -= 100;\r
+ }\r
+\r
+ (code, modes)\r
}\r
\r
-fn execute_op_code(code: &mut [i32], input: &[i32]) -> Vec<i32> {\r
+pub fn execute_op_code(code: &mut [i32], input: &[i32]) -> Vec<i32> {\r
let mut cursor = 0;\r
+ let mut input_cursor = 0;\r
let mut output = Vec::<i32>::new();\r
+\r
+ fn read(position: usize, code: &[i32], mode: bool) -> i32 {\r
+ if mode { code[position] } else { code[code[position] as usize] }\r
+ };\r
+\r
+ fn jump_if(cond: bool, cursor: usize, code: &[i32], modes: [bool; 3]) -> usize {\r
+ let value = read(cursor + 1, &code, modes[0]);\r
+ if cond == (value != 0) {\r
+ read(cursor + 2, &code, modes[1]) as usize\r
+ } else {\r
+ cursor + 3\r
+ }\r
+ };\r
+\r
loop {\r
- match code[cursor] {\r
- 1 => code[code[cursor + 3] as usize] = code[code[cursor + 1] as usize] + code[code[cursor + 2] as usize],\r
- 2 => code[code[cursor + 3] as usize] = code[code[cursor + 1] as usize] * code[code[cursor + 2] as usize],\r
- 99 => return code[0],\r
+ let (op, modes) = read_op_and_modes(code[cursor]);\r
+\r
+ match op {\r
+ // Sum.\r
+ 1 => {\r
+ code[code[cursor + 3] as usize] = read(cursor + 1, &code, modes[0]) + read(cursor + 2, &code, modes[1]);\r
+ cursor += 4;\r
+ },\r
+\r
+ // Multiply.\r
+ 2 => {\r
+ code[code[cursor + 3] as usize] = read(cursor + 1, &code, modes[0]) * read(cursor + 2, &code, modes[1]);\r
+ cursor += 4;\r
+ },\r
+\r
+ // Input.\r
+ 3 => {\r
+ code[code[cursor + 1] as usize] = input[input_cursor];\r
+ input_cursor += 1;\r
+ cursor += 2;\r
+ }\r
+\r
+ // Output.\r
+ 4 => {\r
+ output.push(read(cursor + 1, &code, modes[0]));\r
+ cursor += 2;\r
+ }\r
+\r
+ // Jump-if-true.\r
+ 5 => cursor = jump_if(true, cursor, &code, modes),\r
+\r
+ // Jump-if-false.\r
+ 6 => cursor = jump_if(false, cursor, &code, modes),\r
+\r
+ // Less than.\r
+ 7 => {\r
+ code[code[cursor + 3] as usize] =\r
+ if read(cursor + 1, &code, modes[0]) < read(cursor + 2, &code, modes[1]) { 1 } else { 0 };\r
+ cursor += 4;\r
+ },\r
+\r
+ // Equals.\r
+ 8 => {\r
+ code[code[cursor + 3] as usize] =\r
+ if read(cursor + 1, &code, modes[0]) == read(cursor + 2, &code, modes[1]) { 1 } else { 0 };\r
+ cursor += 4;\r
+ },\r
+\r
+ 99 => break,\r
_ => panic!("Unkown code: {}", code[cursor])\r
}\r
- cursor += 4;\r
}\r
+ output\r
}\r
\r
-\r
-\r
-\r
#[cfg(test)]\r
mod tests {\r
use super::*;\r
\r
#[test]\r
fn part1() {\r
+ let mut c = [1002, 4, 3, 4, 33];\r
+ let _ = execute_op_code(&mut c, &Vec::new());\r
+ assert_eq!(c[4], 99);\r
}\r
\r
#[test]\r
fn part2() {\r
+ let c = [3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99];\r
+\r
+ let mut c1 = c;\r
+ let r1 = execute_op_code(&mut c1, &[7]);\r
+ assert_eq!(r1[0], 999);\r
+\r
+ let mut c2 = c;\r
+ let r2 = execute_op_code(&mut c2, &[8]);\r
+ assert_eq!(r2[0], 1000);\r
+\r
+ let mut c3 = c;\r
+ let r3 = execute_op_code(&mut c3, &[9]);\r
+ assert_eq!(r3[0], 1001);\r
}\r
}
\ No newline at end of file