Commit 87b8d25d authored by Marcel Behrmann's avatar Marcel Behrmann

day(19): part 2 solved

parent b696618f
use crate::utils;
use std::collections::VecDeque;
use std::collections::{VecDeque, HashMap};
#[allow(dead_code)]
pub struct IntVM {
......@@ -7,12 +7,15 @@ pub struct IntVM {
pub input: VecDeque<i64>,
pub output: VecDeque<i64>,
pub memory: Vec<i64>,
pub mem_len: usize,
pub instr_ptr: usize,
pub is_halted: bool,
pub is_waiting_input: bool,
pub print_output: bool,
pub relative_offset: i64,
pub extended_memory: HashMap<usize, i64>,
update_pointer: bool,
tick_length: usize,
}
......@@ -21,24 +24,30 @@ impl IntVM {
#[allow(dead_code)]
pub fn reset(&mut self) {
self.memory = self.rom.clone();
self.extended_memory = HashMap::new();
self.instr_ptr = 0;
self.is_halted = false;
for _ in 0..(1000*2048) {
self.memory.push(0);
}
}
#[allow(dead_code)]
pub fn set_mem(&mut self, address: usize, value: i64) {
self.memory[address] = value;
if self.mem_len > address {
self.memory[address] = value;
} else {
*self.extended_memory.entry(address).or_insert(0) = value;
}
}
pub fn get_mem(&self, address: usize) -> i64 {
if self.mem_len > address {
return self.memory[address];
}
**self.extended_memory.get(&address).get_or_insert(&0)
}
pub fn get_input(&mut self, arg_count: usize) -> i64 {
let instruction = self.memory[self.instr_ptr];
let instruction = self.get_mem(self.instr_ptr);
let mode = (instruction / (10 as i64).pow((arg_count + 2) as u32)) % 10;
if arg_count + 2 > self.tick_length {
......@@ -46,10 +55,10 @@ impl IntVM {
}
match mode {
0 => self.memory[self.memory[self.instr_ptr + 1 + arg_count] as usize],
1 => self.memory[self.instr_ptr + 1 + arg_count],
2 => self.memory[(self.relative_offset + self.memory[self.instr_ptr+1+arg_count]) as usize],
_ => self.memory[self.memory[self.instr_ptr + 1 + arg_count] as usize],
0 => self.get_mem(self.get_mem(self.instr_ptr + 1 + arg_count) as usize),
1 => self.get_mem(self.instr_ptr + 1 + arg_count),
2 => self.get_mem((self.relative_offset + self.get_mem(self.instr_ptr+1+arg_count)) as usize),
_ => self.get_mem(self.get_mem(self.instr_ptr + 1 + arg_count) as usize),
}
}
......@@ -58,7 +67,7 @@ impl IntVM {
self.tick_length = arg_count + 2;
}
let instruction = self.memory[self.instr_ptr];
let instruction = self.get_mem(self.instr_ptr);
let mode = (instruction / (10 as i64).pow((arg_count + 2) as u32)) % 10;
if arg_count + 2 > self.tick_length {
......@@ -66,8 +75,8 @@ impl IntVM {
}
match mode {
2 => (self.relative_offset + self.memory[self.instr_ptr+1+arg_count]) as usize,
_ => self.memory[self.instr_ptr + arg_count + 1] as usize,
2 => (self.relative_offset + self.get_mem(self.instr_ptr+1+arg_count)) as usize,
_ => self.get_mem(self.instr_ptr + arg_count + 1) as usize,
}
}
......@@ -95,7 +104,7 @@ impl IntVM {
self.pre_tick();
let op: i64 = self.memory[self.instr_ptr] % 100;
let op: i64 = self.get_mem(self.instr_ptr) % 100;
match op {
1 => {
......@@ -115,12 +124,12 @@ impl IntVM {
3 => {
let target = self.get_target(0);
if self.input.len() == 0 {
if let Some(input) = self.input.pop_front() {
self.set_mem(target, input);
} else {
self.is_waiting_input = true;
return;
}
self.memory[target] = self.input.pop_front().expect("No input provieded?!");
}
},
4 => {
let target = self.get_input(0);
......@@ -155,9 +164,9 @@ impl IntVM {
let target = self.get_target(2);
if a < b {
self.memory[target] = 1;
self.set_mem(target, 1);
} else {
self.memory[target] = 0;
self.set_mem(target, 0);
}
},
8 => {
......@@ -167,9 +176,9 @@ impl IntVM {
let target = self.get_target(2);
if a == b {
self.memory[target] = 1;
self.set_mem(target, 1);
} else {
self.memory[target] = 0;
self.set_mem(target, 0);
}
},
9 => {
......@@ -180,7 +189,7 @@ impl IntVM {
self.is_halted = true;
},
_ => {
println!("Unknown OPCode ({}, {}, {}, {}) update IntVM", op, self.memory[self.instr_ptr + 1], self.memory[self.instr_ptr + 2], self.memory[self.instr_ptr + 3]);
println!("Unknown OPCode ({}, {}, {}, {}) update IntVM", op, self.get_mem(self.instr_ptr + 1), self.get_mem(self.instr_ptr + 2), self.get_mem(self.instr_ptr + 3));
self.is_halted = true;
},
}
......@@ -190,7 +199,7 @@ impl IntVM {
#[allow(dead_code)]
pub fn get_output(&mut self) -> i64 {
return self.memory[0];
self.get_mem(0)
}
#[allow(dead_code)]
......@@ -207,13 +216,16 @@ impl IntVM {
#[allow(dead_code)]
pub fn create_vm(input: &Vec<&str>) -> IntVM {
let rom = utils::vec_to_int(input.clone());
let mut vm = IntVM {
rom: utils::vec_to_int(input.clone()),
rom: rom.clone(),
print_output: false,
instr_ptr: 0,
is_halted: false,
is_waiting_input: false,
memory: utils::vec_to_int(input.clone()),
memory: rom.clone(),
mem_len: rom.len(),
extended_memory: HashMap::new(),
input: VecDeque::new(),
output: VecDeque::new(),
relative_offset: 0,
......@@ -221,9 +233,5 @@ pub fn create_vm(input: &Vec<&str>) -> IntVM {
tick_length: 0,
};
for _ in 0..(1000*2048) {
vm.memory.push(0);
}
vm
}
\ No newline at end of file
mod utils;
mod intvm;
use std::{thread, time};
use std::fs;
use std::collections::{HashMap, VecDeque};
use std::collections::VecDeque;
const INPUT_FILE: &str = "input.txt";
const SHOW_GAME: bool = true;
fn main() {
let file = &fs::read_to_string(INPUT_FILE).expect("Error reading input");
......@@ -54,44 +52,56 @@ fn part_01(input: &Vec<&str>) -> i64 {
#[allow(unused_variables)]
fn part_02(input: &Vec<&str>) -> i64{
let mut vm = intvm::create_vm(input);
let mut count = 0;
let offset = (3, 5);
let found = false;
let mut r = 0;
let mut width = 0;
let mut current = (0, 100);
while width < 126 {
r += 1;
width = get_count_for_row(r);
}
for _ in 0..10000 {
while !is_on_beam(&mut vm, current) {
current.0 += 1;
}
let width_deeper = get_count_for_row(r+100);
println!("Row {} is 126", r);
println!("Row {} is {}", r+100, width_deeper);
println!("Checking row: {:?}", current.1);
count
}
for offset in 0..200 {
if !is_on_beam(&mut vm, (current.0 + offset + 99, current.1)) {
break;
}
fn get_count_for_row(row: i64) -> i64 {
let mut queue = VecDeque::from(vec![4, 4, 4, 3]);
//println!("\ttop right corner is in the beam");
let mut r = 0;
let mut width = 1;
if !is_on_beam(&mut vm, (current.0 + offset, current.1 + 99)) {
continue;
}
while r < row {
let q = queue.pop_front().unwrap();
queue.push_back(q);
let mut qc = 0;
//println!("\tbottom left corner is in the beam");
while r < row && qc < q {
r += 1;
qc += 1;
//println!("{:?}", (current.0 + offset, current.1));
return (current.0 + offset) * 10_000 + current.1;
}
if r < row {
width += 1;
}
current.1 += 1;
}
width
}
\ No newline at end of file
//let width_deeper = get_count_for_row(r+200);
//println!("Should fit here: {},{}", x, y);
0
}
fn is_on_beam(vm: &mut intvm::IntVM, coords: (i64, i64)) -> bool {
vm.reset();
vm.input.push_back(coords.0);
vm.input.push_back(coords.1);
vm.run();
if let Some(output) = vm.output.pop_back() {
return output == 1;
}
panic!("VM Crashed");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment