day05 task 1
This commit is contained in:
157
src/tasks/day05.rs
Normal file
157
src/tasks/day05.rs
Normal 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());
|
||||
}
|
||||
Reference in New Issue
Block a user