day05 task 1

This commit is contained in:
Johannes
2019-12-08 12:10:29 +01:00
parent 226ac1149b
commit 9e468bde17
7 changed files with 163 additions and 1 deletions

157
src/tasks/day05.rs Normal file
View File

@@ -0,0 +1,157 @@
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day05.txt").unwrap();
let ram: Vec<i32> = input
.split(",")
.map(|s| s.parse::<i32>().unwrap())
.collect();
task1(ram.clone());
}
struct IntCodeComputer {
input_storage: Vec<i32>,
output_storage: Vec<i32>,
pc: usize,
ram: Vec<i32>,
}
#[derive(PartialEq, Debug)]
enum OpCode {
Add,
Multiply,
Input,
Output,
Terminate,
}
#[derive(Debug)]
enum OpParam {
Immediate(i32),
Memory(usize),
}
impl OpParam {
fn from(val: i32, type_number: i32) -> Self {
match type_number {
0 => OpParam::Memory(val as usize),
1 => OpParam::Immediate(val),
_ => unreachable!("unexpected parameter"),
}
}
fn retrieve(&self, memory: &Vec<i32>) -> i32 {
match self {
OpParam::Immediate(v) => *v,
OpParam::Memory(i) => memory[*i],
}
}
fn store(&self, memory: &mut Vec<i32>, value: i32) {
match self {
OpParam::Immediate(_) => panic!("cannot save to immediate position"),
OpParam::Memory(i) => memory[*i] = value,
}
}
}
#[derive(Debug)]
struct Op {
opcode: OpCode,
params: Vec<OpParam>,
}
impl Op {
fn from(pc: usize, memory: &Vec<i32>) -> Self {
//opcode: 123xx -> 1, 2, 3: parameter type for parameters 1-3, xx = actual op code
let mut opcode = memory[pc];
let p_type1 = opcode / 10_000;
opcode %= 10_000;
let p_type2 = opcode / 1000;
opcode %= 1000;
let p_type3 = opcode / 100;
opcode %= 100;
match opcode {
1 => Op {
opcode: OpCode::Add,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
],
},
2 => Op {
opcode: OpCode::Multiply,
params: vec![
OpParam::from(memory[pc + 1], p_type3),
OpParam::from(memory[pc + 2], p_type2),
OpParam::from(memory[pc + 3], p_type1),
],
},
3 => Op {
opcode: OpCode::Input,
params: vec![OpParam::from(memory[pc + 1], p_type3)],
},
4 => Op {
opcode: OpCode::Output,
params: vec![OpParam::from(memory[pc + 1], p_type3)],
},
99 => Op {
opcode: OpCode::Terminate,
params: vec![],
},
_ => unreachable!("unknown op code {}", opcode),
}
}
}
impl IntCodeComputer {
fn new(input: Vec<i32>, memory: Vec<i32>) -> Self {
IntCodeComputer {
input_storage: input,
output_storage: Vec::new(),
pc: 0,
ram: memory,
}
}
fn run_until_end(&mut self) {
let mut op = Op::from(self.pc, &self.ram);
let mut inputs = self.input_storage.iter();
while op.opcode != OpCode::Terminate {
match op.opcode {
OpCode::Add => {
let r = op.params[0].retrieve(&self.ram) + op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Multiply => {
let r = op.params[0].retrieve(&self.ram) * op.params[1].retrieve(&self.ram);
op.params[2].store(&mut self.ram, r);
self.pc += 4;
}
OpCode::Input => {
let v = inputs.next().expect("Not enough inputs given");
op.params[0].store(&mut self.ram, *v);
self.pc += 2;
}
OpCode::Output => {
self.output_storage.push(op.params[0].retrieve(&self.ram));
self.pc += 2;
}
OpCode::Terminate => {}
}
op = Op::from(self.pc, &self.ram);
}
}
fn get_output(&self) -> &[i32] {
self.output_storage.as_slice()
}
}
fn task1(ram: Vec<i32>) {
let mut computer = IntCodeComputer::new(vec![1], ram);
computer.run_until_end();
println!("{:?}", computer.get_output());
println!("Task 1: {}", computer.get_output().last().unwrap());
}