diff options
author | cos <cos> | 2019-12-05 11:10:36 +0100 |
---|---|---|
committer | cos <cos> | 2019-12-05 11:10:36 +0100 |
commit | 3f751c75fa02eb3aedbb56ef17c09eed8d2e162d (patch) | |
tree | aab9416b45cab40ce624850da06cffcb3c366d8a /2019/rust/day05 | |
parent | d0ac44d6d968e6eb385a631745b63a5824908046 (diff) | |
download | adventofcode-3f751c75fa02eb3aedbb56ef17c09eed8d2e162d.zip |
Add day05, 2019
Diffstat (limited to '2019/rust/day05')
-rw-r--r-- | 2019/rust/day05/Cargo.toml | 7 | ||||
-rw-r--r-- | 2019/rust/day05/src/main.rs | 144 |
2 files changed, 151 insertions, 0 deletions
diff --git a/2019/rust/day05/Cargo.toml b/2019/rust/day05/Cargo.toml new file mode 100644 index 0000000..0c5a90e --- /dev/null +++ b/2019/rust/day05/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day05" +version = "0.1.0" +authors = ["cos <cos>"] +edition = "2018" + +[dependencies] diff --git a/2019/rust/day05/src/main.rs b/2019/rust/day05/src/main.rs new file mode 100644 index 0000000..1f93326 --- /dev/null +++ b/2019/rust/day05/src/main.rs @@ -0,0 +1,144 @@ +use std::io::{self, BufRead}; +use std::env; + +fn read_program() -> Vec<i32> { + let stdin = io::stdin(); + + stdin.lock().split(b',').map(|v| { + let s = String::from_utf8(v.unwrap()).unwrap(); + let u:i32 = s.trim_end().parse().unwrap(); + u as i32 + }).collect() +} + +#[derive(Debug)] +enum Arithm { + Add, + Mul, + LessThan, + Equals, +} + +#[derive(Debug)] +enum IO { + In, + Out, +} + +#[derive(Debug)] +enum Jmp { + JmpTrue, + JmpFalse, +} + +#[derive(Debug, PartialEq)] +enum ParameterMode { + Position, + Immediate, +} + +fn arithm(op:Arithm, ip:usize, modes:Vec<ParameterMode>, memory:&mut Vec<i32>) { + if modes[2] == ParameterMode::Immediate { + panic!("Instruction can not store in immediate mode parameter. (IP: {})", ip); + } + let params:Vec<usize> = (0..=2).map(|n| match &modes[n] { + ParameterMode::Position => memory[ip + n + 1] as usize, + ParameterMode::Immediate => ip + n + 1, + }).collect(); + let left = params[0]; + let right = params[1]; + let result = params[2]; + + match op { + Arithm::Add => memory[result] = memory[left] + memory[right], + Arithm::Mul => memory[result] = memory[left] * memory[right], + Arithm::LessThan => memory[result] = if memory[left] < memory[right] { 1 } else { 0 }, + Arithm::Equals => memory[result] = if memory[left] == memory[right] { 1 } else { 0 }, + } +} + +fn jmp(op:Jmp, ip:usize, modes:Vec<ParameterMode>, memory:&mut Vec<i32>) -> usize { + let params:Vec<usize> = (0..=2).map(|n| match &modes[n] { + ParameterMode::Position => memory[ip + n + 1] as usize, + ParameterMode::Immediate => ip + n + 1, + }).collect(); + let value = params[0]; + let address = params[1]; + + match op { + Jmp::JmpTrue => (if memory[value] != 0 { memory[address] as usize } else { ip + 3 }), + Jmp::JmpFalse => (if memory[value] == 0 { memory[address] as usize } else { ip + 3 }), + } +} + +fn io(op:IO, ip:usize, modes:Vec<ParameterMode>, memory:&mut Vec<i32>, keyboard:i32) { + match op { + IO::In => { + let address = match &modes[0] { + ParameterMode::Position => memory[ip + 1] as usize, + ParameterMode::Immediate => + panic!("Cannot store input in immediate mode parameter. (IP: {})", ip), + }; + memory[address] = keyboard; + }, + IO::Out => { + println!("Output: {}", match &modes[0] { + ParameterMode::Position => memory[memory[ip + 1] as usize], + ParameterMode::Immediate => memory[ip + 1], + }); + }, + } +} + +fn intcode(mut memory:Vec<i32>, keyboard:i32) { + let mut ip = 0; + while ip < memory.len() { + let op = memory[ip] % 100; + let modes:Vec<ParameterMode> = (2..=4).map(|e| memory[ip] / 10i32.pow(e) % 10) + .map(|n| match n { + 0 => ParameterMode::Position, + 1 => ParameterMode::Immediate, + p => panic!("Invalid parameter mode {} at IP: {}", p, ip), + }).collect(); + match op { + 1 => { arithm(Arithm::Add, ip, modes, &mut memory); ip += 4 }, + 2 => { arithm(Arithm::Mul, ip, modes, &mut memory); ip += 4 }, + 7 => { arithm(Arithm::LessThan, ip, modes, &mut memory); ip += 4 }, + 8 => { arithm(Arithm::Equals, ip, modes, &mut memory); ip += 4 }, + 3 => { io(IO::In, ip, modes, &mut memory, keyboard); ip += 2 }, + 4 => { io(IO::Out, ip, modes, &mut memory, keyboard); ip += 2 }, + 5 => { ip = jmp(Jmp::JmpTrue, ip, modes, &mut memory); }, + 6 => { ip = jmp(Jmp::JmpFalse, ip, modes, &mut memory); }, + 99 => break, + op => panic!("Invalid operation {} at IP: {}", op, ip), + } + } +} + +fn first_puzzle(memory:Vec<i32>, input:i32) { + println!("Attemping to solve first puzzle. Using input: {}.", input); + + intcode(memory, input); +} + +fn second_puzzle(memory:Vec<i32>, input:i32) { + println!("Attemping to solve second puzzle. Using input: {}.", input); + + intcode(memory, input); +} + +fn main() { + let memory = read_program(); + let input = env::args().nth(1); + + match input { + Some(i) => { + println!("Attemping to run program using input: {}.", i); + intcode(memory, i.parse().unwrap()); + }, + None => { + first_puzzle(memory.clone(), 1); + second_puzzle(memory, 5); + } + } +} |