From 3f751c75fa02eb3aedbb56ef17c09eed8d2e162d Mon Sep 17 00:00:00 2001 From: cos Date: Thu, 5 Dec 2019 11:10:36 +0100 Subject: Add day05, 2019 --- 2019/rust/day05/src/main.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 2019/rust/day05/src/main.rs (limited to '2019/rust/day05/src/main.rs') 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 { + 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, memory:&mut Vec) { + if modes[2] == ParameterMode::Immediate { + panic!("Instruction can not store in immediate mode parameter. (IP: {})", ip); + } + let params:Vec = (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, memory:&mut Vec) -> usize { + let params:Vec = (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, memory:&mut Vec, 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, keyboard:i32) { + let mut ip = 0; + while ip < memory.len() { + let op = memory[ip] % 100; + let modes:Vec = (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, input:i32) { + println!("Attemping to solve first puzzle. Using input: {}.", input); + + intcode(memory, input); +} + +fn second_puzzle(memory:Vec, 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); + } + } +} -- cgit v1.2.3