day09 prepared IntCodeComputer to use HashSet memory and new intructions
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
mod tasks;
|
||||
|
||||
fn main() {
|
||||
tasks::day05::run();
|
||||
tasks::day09::run();
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type RAM = HashMap<usize, i128>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn run() {
|
||||
let input = std::fs::read_to_string("input/day05.txt").unwrap();
|
||||
let ram: Vec<i32> = input
|
||||
let ram: RAM = input
|
||||
.split(",")
|
||||
.map(|s| s.parse::<i32>().unwrap())
|
||||
.enumerate()
|
||||
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
|
||||
.collect();
|
||||
task1(ram.clone());
|
||||
task2(ram.clone());
|
||||
}
|
||||
|
||||
pub struct IntCodeComputer {
|
||||
input_storage: Vec<i32>,
|
||||
output_storage: Vec<i32>,
|
||||
input_storage: Vec<i128>,
|
||||
output_storage: Vec<i128>,
|
||||
pc: usize,
|
||||
ram: Vec<i32>,
|
||||
ram: RAM,
|
||||
relative_base_offset: i128,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
@@ -26,35 +32,44 @@ enum OpCode {
|
||||
JumpIfFalse,
|
||||
LessThan,
|
||||
Equals,
|
||||
AdjustRelBase,
|
||||
Terminate,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum OpParam {
|
||||
Immediate(i32),
|
||||
Immediate(i128),
|
||||
Memory(usize),
|
||||
Relative(i128),
|
||||
}
|
||||
|
||||
impl OpParam {
|
||||
fn from(val: i32, type_number: i32) -> Self {
|
||||
fn from(val: i128, type_number: i128) -> Self {
|
||||
match type_number {
|
||||
0 => OpParam::Memory(val as usize),
|
||||
1 => OpParam::Immediate(val),
|
||||
2 => OpParam::Relative(val),
|
||||
_ => unreachable!("unexpected parameter"),
|
||||
}
|
||||
}
|
||||
|
||||
fn retrieve(&self, memory: &Vec<i32>) -> i32 {
|
||||
fn retrieve(&self, memory: &RAM, relative_base_offset: i128) -> i128 {
|
||||
match self {
|
||||
OpParam::Immediate(v) => *v,
|
||||
OpParam::Memory(i) => memory[*i],
|
||||
OpParam::Memory(i) => memory.get_default(*i),
|
||||
OpParam::Relative(i) => memory.get_default((relative_base_offset + *i) as usize),
|
||||
}
|
||||
}
|
||||
|
||||
fn store(&self, memory: &mut Vec<i32>, value: i32) {
|
||||
fn store(&self, memory: &mut RAM, value: i128, relative_base_offset: i128) {
|
||||
match self {
|
||||
OpParam::Immediate(_) => panic!("cannot save to immediate position"),
|
||||
OpParam::Memory(i) => memory[*i] = value,
|
||||
OpParam::Memory(i) => {
|
||||
memory.insert(*i, value);
|
||||
}
|
||||
OpParam::Relative(i) => {
|
||||
memory.insert((relative_base_offset + *i) as usize, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,9 +81,9 @@ struct Op {
|
||||
}
|
||||
|
||||
impl Op {
|
||||
fn from(pc: usize, memory: &Vec<i32>) -> Self {
|
||||
fn from(pc: usize, memory: &RAM) -> Self {
|
||||
//opcode: 123xx -> 1, 2, 3: parameter type for parameters 1-3, xx = actual op code
|
||||
let mut opcode = memory[pc];
|
||||
let mut opcode = memory.get_default(pc);
|
||||
let p_type1 = opcode / 10_000;
|
||||
opcode %= 10_000;
|
||||
let p_type2 = opcode / 1000;
|
||||
@@ -79,57 +94,61 @@ impl Op {
|
||||
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),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
OpParam::from(memory.get_default(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),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
OpParam::from(memory.get_default(pc + 3), p_type1),
|
||||
],
|
||||
},
|
||||
3 => Op {
|
||||
opcode: OpCode::Input,
|
||||
params: vec![OpParam::from(memory[pc + 1], p_type3)],
|
||||
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
|
||||
},
|
||||
4 => Op {
|
||||
opcode: OpCode::Output,
|
||||
params: vec![OpParam::from(memory[pc + 1], p_type3)],
|
||||
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
|
||||
},
|
||||
5 => Op {
|
||||
opcode: OpCode::JumpIfTrue,
|
||||
params: vec![
|
||||
OpParam::from(memory[pc + 1], p_type3),
|
||||
OpParam::from(memory[pc + 2], p_type2),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
],
|
||||
},
|
||||
6 => Op {
|
||||
opcode: OpCode::JumpIfFalse,
|
||||
params: vec![
|
||||
OpParam::from(memory[pc + 1], p_type3),
|
||||
OpParam::from(memory[pc + 2], p_type2),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
],
|
||||
},
|
||||
7 => Op {
|
||||
opcode: OpCode::LessThan,
|
||||
params: vec![
|
||||
OpParam::from(memory[pc + 1], p_type3),
|
||||
OpParam::from(memory[pc + 2], p_type2),
|
||||
OpParam::from(memory[pc + 3], p_type1),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
OpParam::from(memory.get_default(pc + 3), p_type1),
|
||||
],
|
||||
},
|
||||
8 => Op {
|
||||
opcode: OpCode::Equals,
|
||||
params: vec![
|
||||
OpParam::from(memory[pc + 1], p_type3),
|
||||
OpParam::from(memory[pc + 2], p_type2),
|
||||
OpParam::from(memory[pc + 3], p_type1),
|
||||
OpParam::from(memory.get_default(pc + 1), p_type3),
|
||||
OpParam::from(memory.get_default(pc + 2), p_type2),
|
||||
OpParam::from(memory.get_default(pc + 3), p_type1),
|
||||
],
|
||||
},
|
||||
9 => Op {
|
||||
opcode: OpCode::AdjustRelBase,
|
||||
params: vec![OpParam::from(memory.get_default(pc + 1), p_type3)],
|
||||
},
|
||||
99 => Op {
|
||||
opcode: OpCode::Terminate,
|
||||
params: vec![],
|
||||
@@ -140,12 +159,13 @@ impl Op {
|
||||
}
|
||||
|
||||
impl IntCodeComputer {
|
||||
pub fn new(input: Vec<i32>, memory: Vec<i32>) -> Self {
|
||||
pub fn new(input: Vec<i128>, memory: RAM) -> Self {
|
||||
IntCodeComputer {
|
||||
input_storage: input,
|
||||
output_storage: Vec::new(),
|
||||
pc: 0,
|
||||
ram: memory,
|
||||
relative_base_offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,60 +184,73 @@ impl IntCodeComputer {
|
||||
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);
|
||||
let r = op.params[0].retrieve(&self.ram, self.relative_base_offset)
|
||||
+ op.params[1].retrieve(&self.ram, self.relative_base_offset);
|
||||
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
|
||||
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);
|
||||
let r = op.params[0].retrieve(&self.ram, self.relative_base_offset)
|
||||
* op.params[1].retrieve(&self.ram, self.relative_base_offset);
|
||||
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
|
||||
self.pc += 4;
|
||||
}
|
||||
OpCode::Input => {
|
||||
if let Some(v) = inputs.next() {
|
||||
op.params[0].store(&mut self.ram, *v);
|
||||
op.params[0].store(&mut self.ram, *v, self.relative_base_offset);
|
||||
self.pc += 2;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
OpCode::Output => {
|
||||
self.output_storage.push(op.params[0].retrieve(&self.ram));
|
||||
self.output_storage
|
||||
.push(op.params[0].retrieve(&self.ram, self.relative_base_offset));
|
||||
self.pc += 2;
|
||||
}
|
||||
OpCode::JumpIfTrue => {
|
||||
if op.params[0].retrieve(&self.ram) > 0 {
|
||||
self.pc = op.params[1].retrieve(&self.ram) as usize;
|
||||
if op.params[0].retrieve(&self.ram, self.relative_base_offset) > 0 {
|
||||
self.pc =
|
||||
op.params[1].retrieve(&self.ram, self.relative_base_offset) as usize;
|
||||
} else {
|
||||
self.pc += 3;
|
||||
}
|
||||
}
|
||||
OpCode::JumpIfFalse => {
|
||||
if op.params[0].retrieve(&self.ram) == 0 {
|
||||
self.pc = op.params[1].retrieve(&self.ram) as usize;
|
||||
if op.params[0].retrieve(&self.ram, self.relative_base_offset) == 0 {
|
||||
self.pc =
|
||||
op.params[1].retrieve(&self.ram, self.relative_base_offset) as usize;
|
||||
} else {
|
||||
self.pc += 3;
|
||||
}
|
||||
}
|
||||
OpCode::LessThan => {
|
||||
let r = if op.params[0].retrieve(&self.ram) < op.params[1].retrieve(&self.ram) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
op.params[2].store(&mut self.ram, r);
|
||||
self.pc += 4;
|
||||
}
|
||||
OpCode::Equals => {
|
||||
let r = if op.params[0].retrieve(&self.ram) == op.params[1].retrieve(&self.ram)
|
||||
let r = if op.params[0].retrieve(&self.ram, self.relative_base_offset)
|
||||
< op.params[1].retrieve(&self.ram, self.relative_base_offset)
|
||||
{
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
op.params[2].store(&mut self.ram, r);
|
||||
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
|
||||
self.pc += 4;
|
||||
}
|
||||
OpCode::Equals => {
|
||||
let r = if op.params[0].retrieve(&self.ram, self.relative_base_offset)
|
||||
== op.params[1].retrieve(&self.ram, self.relative_base_offset)
|
||||
{
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
op.params[2].store(&mut self.ram, r, self.relative_base_offset);
|
||||
self.pc += 4;
|
||||
}
|
||||
OpCode::AdjustRelBase => {
|
||||
self.relative_base_offset +=
|
||||
op.params[0].retrieve(&self.ram, self.relative_base_offset);
|
||||
self.pc += 2;
|
||||
}
|
||||
OpCode::Terminate => {}
|
||||
}
|
||||
op = Op::from(self.pc, &self.ram);
|
||||
@@ -225,7 +258,7 @@ impl IntCodeComputer {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn set_input(&mut self, input: &[i32]) {
|
||||
pub fn set_input(&mut self, input: &[i128]) {
|
||||
self.input_storage.clear();
|
||||
for x in input {
|
||||
self.input_storage.push(*x);
|
||||
@@ -236,21 +269,31 @@ impl IntCodeComputer {
|
||||
self.output_storage.clear();
|
||||
}
|
||||
|
||||
pub fn get_output(&self) -> &[i32] {
|
||||
pub fn get_output(&self) -> &[i128] {
|
||||
self.output_storage.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
fn task1(ram: Vec<i32>) {
|
||||
fn task1(ram: RAM) {
|
||||
let mut computer = IntCodeComputer::new(vec![1], ram);
|
||||
computer.run_until_end();
|
||||
println!("{:?}", computer.get_output());
|
||||
println!("Task 1: {}", computer.get_output().last().unwrap());
|
||||
}
|
||||
|
||||
fn task2(ram: Vec<i32>) {
|
||||
fn task2(ram: RAM) {
|
||||
let mut computer = IntCodeComputer::new(vec![5], ram);
|
||||
computer.run_until_end();
|
||||
println!("{:?}", computer.get_output());
|
||||
println!("Task 2: {}", computer.get_output().last().unwrap());
|
||||
}
|
||||
|
||||
trait Easy {
|
||||
fn get_default(&self, index: usize) -> i128;
|
||||
}
|
||||
|
||||
impl Easy for RAM {
|
||||
fn get_default(&self, index: usize) -> i128 {
|
||||
**self.get(&index).get_or_insert(&0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,20 +6,23 @@ pub fn run() {
|
||||
let prog_code: Vec<_> = std::fs::read_to_string("input/day07.txt")
|
||||
.unwrap()
|
||||
.split(",")
|
||||
.map(|s| s.parse::<i32>().unwrap())
|
||||
.map(|s| s.parse::<i128>().unwrap())
|
||||
.collect();
|
||||
task1(prog_code.clone());
|
||||
task2(prog_code.clone());
|
||||
}
|
||||
|
||||
fn task1(input: Vec<i32>) {
|
||||
fn task1(input: Vec<i128>) {
|
||||
let phases = vec![0, 1, 2, 3, 4];
|
||||
let result = phases
|
||||
.iter()
|
||||
.permutations(phases.len())
|
||||
.map(|perm| {
|
||||
perm.iter().fold(0, |signal, phase| {
|
||||
let mut computer = IntCodeComputer::new(vec![**phase, signal], input.clone());
|
||||
let mut computer = IntCodeComputer::new(
|
||||
vec![**phase, signal],
|
||||
input.clone().into_iter().enumerate().collect(),
|
||||
);
|
||||
computer.run_until_end();
|
||||
*computer.get_output().last().unwrap()
|
||||
})
|
||||
@@ -28,7 +31,7 @@ fn task1(input: Vec<i32>) {
|
||||
println!("Task 1: best signal is {}", result.unwrap());
|
||||
}
|
||||
|
||||
fn task2(input: Vec<i32>) {
|
||||
fn task2(input: Vec<i128>) {
|
||||
let phases = vec![5, 6, 7, 8, 9];
|
||||
let result = phases
|
||||
.iter()
|
||||
@@ -37,7 +40,10 @@ fn task2(input: Vec<i32>) {
|
||||
let mut machines: Vec<IntCodeComputer> = perm
|
||||
.iter()
|
||||
.map(|phase| {
|
||||
let mut comp = IntCodeComputer::new(vec![**phase], input.clone());
|
||||
let mut comp = IntCodeComputer::new(
|
||||
vec![**phase],
|
||||
input.clone().into_iter().enumerate().collect(),
|
||||
);
|
||||
comp.run_until_input_empty();
|
||||
comp
|
||||
})
|
||||
|
||||
@@ -5,3 +5,4 @@ pub mod day05;
|
||||
pub mod day06;
|
||||
pub mod day07;
|
||||
pub mod day08;
|
||||
pub mod day09;
|
||||
|
||||
Reference in New Issue
Block a user