Refactor computer to not use stdin/out for input/output

This commit is contained in:
Wesley Moore 2019-12-07 17:36:42 +11:00
parent b53033b15d
commit 1f34121f0a
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE
2 changed files with 29 additions and 25 deletions

View file

@ -3,10 +3,17 @@ use std::{fs, io};
fn main() -> io::Result<()> { fn main() -> io::Result<()> {
let input = fs::read_to_string("input/day5.txt")?; let input = fs::read_to_string("input/day5.txt")?;
let mut data = input::read_separated_line(',', &input)?; let data = input::read_separated_line(',', &input)?;
let mut program = computer::Computer::new(&mut data);
program.run(None, None); let mut program = data.clone();
let mut computer = computer::Computer::new(&mut program, vec![1]);
computer.run(None, None);
println!("Part 1: {:?}", computer.output());
let mut program = data.clone();
let mut computer = computer::Computer::new(&mut program, vec![5]);
computer.run(None, None);
println!("Part 2: {:?}", computer.output());
Ok(()) Ok(())
} }

View file

@ -1,7 +1,3 @@
use std::io;
use std::io::Write;
use std::str::FromStr;
type Address = i32; type Address = i32;
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
@ -24,7 +20,9 @@ enum Mode {
} }
pub struct Computer<'a> { pub struct Computer<'a> {
mem: &'a mut [i32], memory: &'a mut [i32],
input: Vec<i32>,
output: Vec<i32>,
} }
fn decode(mut instruction: i32) -> Instruction { fn decode(mut instruction: i32) -> Instruction {
@ -67,19 +65,23 @@ fn decode(mut instruction: i32) -> Instruction {
} }
impl<'a> Computer<'a> { impl<'a> Computer<'a> {
pub fn new(mem: &'a mut [i32]) -> Self { pub fn new(memory: &'a mut [i32], input: Vec<i32>) -> Self {
Computer { mem } Computer {
memory,
input,
output: vec![],
}
} }
fn read(&self, value: i32, mode: Mode) -> i32 { fn read(&self, value: i32, mode: Mode) -> i32 {
match mode { match mode {
Mode::Immediate => self.mem[value as usize], Mode::Immediate => self.memory[value as usize],
Mode::Address => self.mem[self.mem[value as usize] as usize], Mode::Address => self.memory[self.memory[value as usize] as usize],
} }
} }
fn write(&mut self, address: Address, value: i32) { fn write(&mut self, address: Address, value: i32) {
self.mem[address as usize] = value; self.memory[address as usize] = value;
} }
pub fn run(&mut self, noun: Option<i32>, verb: Option<i32>) { pub fn run(&mut self, noun: Option<i32>, verb: Option<i32>) {
@ -104,21 +106,12 @@ impl<'a> Computer<'a> {
ip += 4; ip += 4;
} }
Instruction::Input => { Instruction::Input => {
let mut input = String::new(); let value = self.input.pop().expect("no more input");
print!("Input integer: "); self.write(self.read(ip + 1, Mode::Immediate), value);
io::stdout().flush().unwrap();
match io::stdin().read_line(&mut input) {
Ok(_) => {
let integer = i32::from_str(input.trim()).expect("invalid integer");
self.write(self.read(ip + 1, Mode::Immediate), integer);
}
Err(error) => panic!("error: {}", error),
}
ip += 2; ip += 2;
} }
Instruction::Output(mode) => { Instruction::Output(mode) => {
let value = self.read(ip + 1, mode); self.output.push(self.read(ip + 1, mode));
println!("{}", value);
ip += 2; ip += 2;
} }
Instruction::JumpIfTrue(mode1, mode2) => { Instruction::JumpIfTrue(mode1, mode2) => {
@ -155,6 +148,10 @@ impl<'a> Computer<'a> {
} }
} }
} }
pub fn output(&self) -> &[i32] {
&self.output
}
} }
fn divmod(value: &mut i32, divisor: i32) -> i32 { fn divmod(value: &mut i32, divisor: i32) -> i32 {