Day[09]
authorGrégory Burri <gregory.burri@matisa.ch>
Mon, 9 Dec 2019 15:40:37 +0000 (16:40 +0100)
committerGrégory Burri <gregory.burri@matisa.ch>
Mon, 9 Dec 2019 15:40:37 +0000 (16:40 +0100)
src/common.rs
src/day07.rs [new file with mode: 0644]
src/day08.rs [new file with mode: 0644]
src/day09.rs [new file with mode: 0644]
src/main.rs

index e87a0a2..30155d0 100644 (file)
@@ -1,6 +1,13 @@
 use std::fs;\r
 use std::path::Path;\r
+use std::str::FromStr;\r
 \r
-pub fn read_list_of_numbers<P: AsRef<Path>>(file: P, sep: &str) -> Vec<i32> {\r
-    fs::read_to_string(file).unwrap().split(sep).map(|line| line.parse::<i32>().unwrap()).collect()\r
+pub fn read_list_of_numbers<P, T>(file: P, sep: &str) -> Vec<T>\r
+where\r
+    P: AsRef<Path>,\r
+    T: FromStr,\r
+    T::Err: std::fmt::Debug\r
+\r
+{\r
+    fs::read_to_string(file).unwrap().split(sep).map(|line| line.parse::<T>().unwrap()).collect()\r
 }
\ No newline at end of file
diff --git a/src/day07.rs b/src/day07.rs
new file mode 100644 (file)
index 0000000..77d8c48
--- /dev/null
@@ -0,0 +1 @@
+fn fun() { }
\ No newline at end of file
diff --git a/src/day08.rs b/src/day08.rs
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/day09.rs b/src/day09.rs
new file mode 100644 (file)
index 0000000..ea234b2
--- /dev/null
@@ -0,0 +1,152 @@
+#[derive(Copy, Clone, Debug)]\r
+enum Mode {\r
+    Position,\r
+    Immediate,\r
+    Relative\r
+}\r
+\r
+// 'true' -> immediate mode, 'false' -> position mode.\r
+fn read_op_and_modes(mut code: i64) -> (i64, [Mode; 3]) {\r
+    let mut modes: [Mode; 3] = [ Mode::Position, Mode::Position, Mode::Position ];\r
+\r
+    for i in (2..=4).rev() {\r
+        let power = 10i64.pow(i);\r
+        if code >= 2 * power {\r
+            modes[i as usize - 2] = Mode::Relative;\r
+            code -= 2 * power;\r
+        } else if code >= power {\r
+            modes[i as usize - 2] = Mode::Immediate;\r
+            code -= power;\r
+        }\r
+    }\r
+\r
+    (code, modes)\r
+}\r
+\r
+pub fn execute_op_code(code: &[i64], input: &[i64]) -> Vec<i64> {\r
+    let mut code = Vec::from(code);\r
+    let mut cursor = 0;\r
+    let mut input_cursor = 0;\r
+    let mut output = Vec::<i64>::new();\r
+    let mut relative_base = 0;\r
+\r
+    fn read(position: usize, code: &[i64], mode: Mode, relative_base: i64) -> i64 {\r
+        if position >= code.len() { return 0 }\r
+\r
+        match mode {\r
+            Mode::Position => if code[position] as usize >= code.len() { 0 } else { code[code[position] as usize] },\r
+            Mode::Immediate => code[position],\r
+            Mode::Relative => if (code[position] + relative_base) as usize >= code.len() { 0 } else { code[(code[position] + relative_base) as usize] }\r
+        }\r
+    };\r
+\r
+    fn write(position: usize, value: i64, code: &mut Vec<i64>, mode: Mode, relative_base: i64) {\r
+        let ref_position =\r
+            match mode {\r
+                Mode::Position => code[position] as usize,\r
+                Mode::Immediate => panic!("Can't write un immediate mode"),\r
+                Mode::Relative => (code[position] + relative_base) as usize\r
+            };\r
+\r
+        if ref_position >= code.len() {\r
+            code.resize(ref_position + 1, 0);\r
+        }\r
+\r
+        code[ref_position] = value;\r
+    }\r
+\r
+    fn jump_if(cond: bool, cursor: usize, code: &[i64], modes: [Mode; 3], relative_base: i64) -> usize {\r
+        let value = read(cursor + 1, &code, modes[0], relative_base);\r
+        if cond == (value != 0) {\r
+            read(cursor + 2, &code, modes[1], relative_base) as usize\r
+        } else {\r
+            cursor + 3\r
+        }\r
+    };\r
+\r
+    loop {\r
+        let (op, modes) = read_op_and_modes(code[cursor]);\r
+\r
+        match op {\r
+            // Sum.\r
+            1 => {\r
+                write(cursor + 3, read(cursor + 1, &code, modes[0], relative_base) + read(cursor + 2, &code, modes[1], relative_base), &mut code, modes[2], relative_base);\r
+                cursor += 4;\r
+            },\r
+\r
+            // Multiply.\r
+            2 => {\r
+                write(cursor + 3, read(cursor + 1, &code, modes[0], relative_base) * read(cursor + 2, &code, modes[1], relative_base), &mut code, modes[2], relative_base);\r
+                cursor += 4;\r
+            },\r
+\r
+            // Input.\r
+            3 => {\r
+                write(cursor + 1, input[input_cursor], &mut code, modes[0], relative_base);\r
+                input_cursor += 1;\r
+                cursor += 2;\r
+            }\r
+\r
+            // Output.\r
+            4 => {\r
+                output.push(read(cursor + 1, &code, modes[0], relative_base));\r
+                cursor += 2;\r
+            }\r
+\r
+            // Jump-if-true.\r
+            5 => cursor = jump_if(true, cursor, &code, modes, relative_base),\r
+\r
+            // Jump-if-false.\r
+            6 => cursor = jump_if(false, cursor, &code, modes, relative_base),\r
+\r
+            // Less than.\r
+            7 => {\r
+                write(cursor + 3, if read(cursor + 1, &code, modes[0], relative_base) < read(cursor + 2, &code, modes[1], relative_base) { 1 } else { 0 }, &mut code, modes[2], relative_base);\r
+                cursor += 4;\r
+            },\r
+\r
+            // Equals.\r
+            8 => {\r
+                write(cursor + 3, if read(cursor + 1, &code, modes[0], relative_base) == read(cursor + 2, &code, modes[1], relative_base) { 1 } else { 0 }, &mut code, modes[2], relative_base);\r
+                cursor += 4;\r
+            },\r
+\r
+            // Change relative base.\r
+            9 => {\r
+                relative_base += read(cursor + 1, &code, modes[0], relative_base);\r
+                cursor += 2;\r
+            }\r
+\r
+            99 => break,\r
+\r
+            _ => panic!("Unkown code: {}", code[cursor])\r
+        }\r
+    }\r
+    output\r
+}\r
+\r
+#[cfg(test)]\r
+mod tests {\r
+    use super::*;\r
+\r
+    #[test]\r
+    fn copy_of_itself() {\r
+        let c = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99];\r
+        let r = execute_op_code(&c, &Vec::new());\r
+        assert_eq!(r, c);\r
+    }\r
+\r
+    #[test]\r
+    fn output_big_number() {\r
+        let c = [1102,34_915_192,34_915_192,7,4,7,99,0];\r
+        let r = execute_op_code(&c, &Vec::new());\r
+        assert_eq!(r[0], 1_219_070_632_396_864);\r
+    }\r
+\r
+    #[test]\r
+    fn input_big_number() {\r
+        let c = [104,1_125_899_906_842_624,99];\r
+        let r = execute_op_code(&c, &Vec::new());\r
+        assert_eq!(r[0], 1_125_899_906_842_624);\r
+    }\r
+}
\ No newline at end of file
index eaccb71..2c96367 100644 (file)
@@ -7,6 +7,9 @@ mod day02;
 mod day03;
 mod day05;
 mod day06;
+mod day07;
+mod day08;
+mod day09;
 mod common;
 
 fn day01() -> String {
@@ -45,6 +48,19 @@ fn day06() -> String {
     format!("part1: {}, part2: {}", day06::total_direct_and_indirect_orbits(&orbits), day06::nb_orbital_transfers(&orbits, "SAN", "YOU"))
 }
 
+fn day07() -> String {
+    format!("")
+}
+
+fn day08() -> String {
+    format!("")
+}
+
+fn day09() -> String {
+    let code = common::read_list_of_numbers("data/day09.input", ",");
+    format!("part1: {:?}, part2: {:?}", day09::execute_op_code(&code, &[1]), day09::execute_op_code(&code, &[2]))
+}
+
 fn format_micros(t: u128) -> String {
     if t < 10_000 {
         format!("{} μs", t)
@@ -69,7 +85,10 @@ fn main() {
         day03,
         day04,
         day05,
-        day06
+        day06,
+        day07,
+        day08,
+        day09
     );
 
     let args: Vec<String> = env::args().skip(1).collect();