From: Grégory Burri Date: Mon, 9 Dec 2019 15:40:37 +0000 (+0100) Subject: Day[09] X-Git-Url: http://git.euphorik.ch/index.cgi?a=commitdiff_plain;h=91620914391b197fab0624a627f1b0a24ff75364;p=advent_of_code_2019.git Day[09] --- diff --git a/data/day09.input b/data/day09.input new file mode 100644 index 0000000..f0617de --- /dev/null +++ b/data/day09.input @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,902,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,0,32,1009,1101,0,842,1023,1101,0,33,1007,1101,36,0,1015,1101,35,0,1006,1101,0,0,1020,1102,1,25,1005,1101,0,34,1008,1101,0,849,1022,1102,1,1,1021,1101,22,0,1004,1102,1,26,1017,1102,286,1,1029,1101,38,0,1013,1102,20,1,1000,1102,39,1,1002,1101,0,24,1010,1101,0,30,1016,1102,1,27,1019,1102,824,1,1027,1102,216,1,1025,1102,1,28,1001,1101,295,0,1028,1102,29,1,1003,1101,31,0,1011,1102,1,827,1026,1102,1,225,1024,1101,21,0,1012,1102,1,23,1018,1102,37,1,1014,109,19,21102,40,1,-1,1008,1018,40,63,1005,63,203,4,187,1106,0,207,1001,64,1,64,1002,64,2,64,109,1,2105,1,4,4,213,1001,64,1,64,1106,0,225,1002,64,2,64,109,-8,21101,41,0,7,1008,1019,41,63,1005,63,247,4,231,1106,0,251,1001,64,1,64,1002,64,2,64,109,-1,2101,0,-2,63,1008,63,32,63,1005,63,273,4,257,1105,1,277,1001,64,1,64,1002,64,2,64,109,17,2106,0,0,4,283,1001,64,1,64,1106,0,295,1002,64,2,64,109,-13,1202,-6,1,63,1008,63,32,63,1005,63,321,4,301,1001,64,1,64,1105,1,321,1002,64,2,64,109,10,1205,-5,337,1001,64,1,64,1105,1,339,4,327,1002,64,2,64,109,-31,2102,1,9,63,1008,63,32,63,1005,63,363,1001,64,1,64,1105,1,365,4,345,1002,64,2,64,109,22,2107,34,-9,63,1005,63,385,1001,64,1,64,1106,0,387,4,371,1002,64,2,64,109,-2,21108,42,42,1,1005,1015,409,4,393,1001,64,1,64,1105,1,409,1002,64,2,64,109,-2,1208,-9,31,63,1005,63,425,1105,1,431,4,415,1001,64,1,64,1002,64,2,64,109,-3,2108,37,-1,63,1005,63,451,1001,64,1,64,1106,0,453,4,437,1002,64,2,64,109,-9,1201,6,0,63,1008,63,35,63,1005,63,475,4,459,1105,1,479,1001,64,1,64,1002,64,2,64,109,15,2107,33,-7,63,1005,63,497,4,485,1106,0,501,1001,64,1,64,1002,64,2,64,1206,6,515,1001,64,1,64,1105,1,517,4,505,1002,64,2,64,109,-2,2101,0,-7,63,1008,63,32,63,1005,63,541,1001,64,1,64,1105,1,543,4,523,1002,64,2,64,109,-6,2102,1,-2,63,1008,63,25,63,1005,63,569,4,549,1001,64,1,64,1106,0,569,1002,64,2,64,109,5,1201,-8,0,63,1008,63,19,63,1005,63,589,1106,0,595,4,575,1001,64,1,64,1002,64,2,64,109,-16,1207,10,36,63,1005,63,613,4,601,1106,0,617,1001,64,1,64,1002,64,2,64,109,25,1206,-1,631,4,623,1105,1,635,1001,64,1,64,1002,64,2,64,109,-8,21101,43,0,1,1008,1014,46,63,1005,63,655,1106,0,661,4,641,1001,64,1,64,1002,64,2,64,109,-4,2108,33,-2,63,1005,63,683,4,667,1001,64,1,64,1106,0,683,1002,64,2,64,109,1,21107,44,43,0,1005,1010,699,1105,1,705,4,689,1001,64,1,64,1002,64,2,64,109,1,21102,45,1,8,1008,1019,46,63,1005,63,729,1001,64,1,64,1106,0,731,4,711,1002,64,2,64,109,3,1207,-7,32,63,1005,63,751,1001,64,1,64,1106,0,753,4,737,1002,64,2,64,109,7,1205,0,771,4,759,1001,64,1,64,1105,1,771,1002,64,2,64,109,-18,1208,0,29,63,1005,63,789,4,777,1105,1,793,1001,64,1,64,1002,64,2,64,109,16,21107,46,47,-7,1005,1012,811,4,799,1106,0,815,1001,64,1,64,1002,64,2,64,109,17,2106,0,-9,1105,1,833,4,821,1001,64,1,64,1002,64,2,64,109,-10,2105,1,-3,1001,64,1,64,1105,1,851,4,839,1002,64,2,64,109,-16,1202,-6,1,63,1008,63,25,63,1005,63,875,1001,64,1,64,1106,0,877,4,857,1002,64,2,64,109,-1,21108,47,45,5,1005,1014,897,1001,64,1,64,1106,0,899,4,883,4,64,99,21101,27,0,1,21101,0,913,0,1106,0,920,21201,1,28853,1,204,1,99,109,3,1207,-2,3,63,1005,63,962,21201,-2,-1,1,21102,940,1,0,1105,1,920,22102,1,1,-1,21201,-2,-3,1,21101,0,955,0,1105,1,920,22201,1,-1,-2,1106,0,966,22102,1,-2,-2,109,-3,2105,1,0 \ No newline at end of file diff --git a/src/common.rs b/src/common.rs index e87a0a2..30155d0 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,13 @@ use std::fs; use std::path::Path; +use std::str::FromStr; -pub fn read_list_of_numbers>(file: P, sep: &str) -> Vec { - fs::read_to_string(file).unwrap().split(sep).map(|line| line.parse::().unwrap()).collect() +pub fn read_list_of_numbers(file: P, sep: &str) -> Vec +where + P: AsRef, + T: FromStr, + T::Err: std::fmt::Debug + +{ + fs::read_to_string(file).unwrap().split(sep).map(|line| line.parse::().unwrap()).collect() } \ No newline at end of file diff --git a/src/day07.rs b/src/day07.rs new file mode 100644 index 0000000..77d8c48 --- /dev/null +++ b/src/day07.rs @@ -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 index 0000000..e69de29 diff --git a/src/day09.rs b/src/day09.rs new file mode 100644 index 0000000..ea234b2 --- /dev/null +++ b/src/day09.rs @@ -0,0 +1,152 @@ +#[derive(Copy, Clone, Debug)] +enum Mode { + Position, + Immediate, + Relative +} + +// 'true' -> immediate mode, 'false' -> position mode. +fn read_op_and_modes(mut code: i64) -> (i64, [Mode; 3]) { + let mut modes: [Mode; 3] = [ Mode::Position, Mode::Position, Mode::Position ]; + + for i in (2..=4).rev() { + let power = 10i64.pow(i); + if code >= 2 * power { + modes[i as usize - 2] = Mode::Relative; + code -= 2 * power; + } else if code >= power { + modes[i as usize - 2] = Mode::Immediate; + code -= power; + } + } + + (code, modes) +} + +pub fn execute_op_code(code: &[i64], input: &[i64]) -> Vec { + let mut code = Vec::from(code); + let mut cursor = 0; + let mut input_cursor = 0; + let mut output = Vec::::new(); + let mut relative_base = 0; + + fn read(position: usize, code: &[i64], mode: Mode, relative_base: i64) -> i64 { + if position >= code.len() { return 0 } + + match mode { + Mode::Position => if code[position] as usize >= code.len() { 0 } else { code[code[position] as usize] }, + Mode::Immediate => code[position], + Mode::Relative => if (code[position] + relative_base) as usize >= code.len() { 0 } else { code[(code[position] + relative_base) as usize] } + } + }; + + fn write(position: usize, value: i64, code: &mut Vec, mode: Mode, relative_base: i64) { + let ref_position = + match mode { + Mode::Position => code[position] as usize, + Mode::Immediate => panic!("Can't write un immediate mode"), + Mode::Relative => (code[position] + relative_base) as usize + }; + + if ref_position >= code.len() { + code.resize(ref_position + 1, 0); + } + + code[ref_position] = value; + } + + fn jump_if(cond: bool, cursor: usize, code: &[i64], modes: [Mode; 3], relative_base: i64) -> usize { + let value = read(cursor + 1, &code, modes[0], relative_base); + if cond == (value != 0) { + read(cursor + 2, &code, modes[1], relative_base) as usize + } else { + cursor + 3 + } + }; + + loop { + let (op, modes) = read_op_and_modes(code[cursor]); + + match op { + // Sum. + 1 => { + 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); + cursor += 4; + }, + + // Multiply. + 2 => { + 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); + cursor += 4; + }, + + // Input. + 3 => { + write(cursor + 1, input[input_cursor], &mut code, modes[0], relative_base); + input_cursor += 1; + cursor += 2; + } + + // Output. + 4 => { + output.push(read(cursor + 1, &code, modes[0], relative_base)); + cursor += 2; + } + + // Jump-if-true. + 5 => cursor = jump_if(true, cursor, &code, modes, relative_base), + + // Jump-if-false. + 6 => cursor = jump_if(false, cursor, &code, modes, relative_base), + + // Less than. + 7 => { + 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); + cursor += 4; + }, + + // Equals. + 8 => { + 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); + cursor += 4; + }, + + // Change relative base. + 9 => { + relative_base += read(cursor + 1, &code, modes[0], relative_base); + cursor += 2; + } + + 99 => break, + + _ => panic!("Unkown code: {}", code[cursor]) + } + } + output +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn copy_of_itself() { + let c = [109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99]; + let r = execute_op_code(&c, &Vec::new()); + assert_eq!(r, c); + } + + #[test] + fn output_big_number() { + let c = [1102,34_915_192,34_915_192,7,4,7,99,0]; + let r = execute_op_code(&c, &Vec::new()); + assert_eq!(r[0], 1_219_070_632_396_864); + } + + #[test] + fn input_big_number() { + let c = [104,1_125_899_906_842_624,99]; + let r = execute_op_code(&c, &Vec::new()); + assert_eq!(r[0], 1_125_899_906_842_624); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index eaccb71..2c96367 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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 = env::args().skip(1).collect();