summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcos <cos>2019-12-05 11:10:36 +0100
committercos <cos>2019-12-05 11:10:36 +0100
commit3f751c75fa02eb3aedbb56ef17c09eed8d2e162d (patch)
treeaab9416b45cab40ce624850da06cffcb3c366d8a
parentd0ac44d6d968e6eb385a631745b63a5824908046 (diff)
downloadadventofcode-3f751c75fa02eb3aedbb56ef17c09eed8d2e162d.zip
Add day05, 2019
-rw-r--r--2019/rust/Cargo.toml1
-rw-r--r--2019/rust/day05/Cargo.toml7
-rw-r--r--2019/rust/day05/src/main.rs144
3 files changed, 152 insertions, 0 deletions
diff --git a/2019/rust/Cargo.toml b/2019/rust/Cargo.toml
index caf0fc3..acbc8bb 100644
--- a/2019/rust/Cargo.toml
+++ b/2019/rust/Cargo.toml
@@ -4,4 +4,5 @@ members = [
"day02",
"day03",
"day04",
+ "day05",
]
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);
+ }
+ }
+}