Make Computer do I/O in terms of traits

This commit is contained in:
Wesley Moore 2019-12-08 10:07:15 +11:00
parent af694da6ce
commit 5965959a05
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE
3 changed files with 42 additions and 16 deletions

View file

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

View file

@ -25,9 +25,9 @@ fn part1(data: Vec<i32>) {
let mut output = 0; let mut output = 0;
for phase_setting in settings.iter() { for phase_setting in settings.iter() {
let input = vec![output, *phase_setting]; let input = vec![output, *phase_setting];
let mut computer = computer::Computer::new(data.clone(), input); let mut computer = computer::Computer::new(data.clone(), input, vec![]);
computer.run(None, None); computer.run(None, None);
output = computer.output()[0]; output = computer.output();
} }
output output
}) })

View file

@ -19,10 +19,36 @@ enum Mode {
Address, Address,
} }
pub struct Computer { pub struct Computer<I: Input, O: Output> {
memory: Vec<i32>, memory: Vec<i32>,
input: Vec<i32>, input: I,
output: Vec<i32>, output: O,
}
pub trait Input {
fn read(&mut self) -> Option<i32>;
}
pub trait Output {
fn write(&mut self, value: i32);
fn last_value(&self) -> i32;
}
impl Input for Vec<i32> {
fn read(&mut self) -> Option<i32> {
self.pop()
}
}
impl Output for Vec<i32> {
fn write(&mut self, value: i32) {
self.push(value)
}
fn last_value(&self) -> i32 {
*self.last().unwrap()
}
} }
fn decode(mut instruction: i32) -> Instruction { fn decode(mut instruction: i32) -> Instruction {
@ -64,12 +90,12 @@ fn decode(mut instruction: i32) -> Instruction {
} }
} }
impl Computer { impl<I, O> Computer<I, O> where I: Input, O: Output {
pub fn new(memory: Vec<i32>, input: Vec<i32>) -> Self { pub fn new(memory: Vec<i32>, input: I, output: O) -> Self {
Computer { Computer {
memory, memory,
input, input,
output: vec![], output,
} }
} }
@ -106,12 +132,12 @@ impl Computer {
ip += 4; ip += 4;
} }
Instruction::Input => { Instruction::Input => {
let value = self.input.pop().expect("no more input"); let value = self.input.read().expect("no more input");
self.write(self.read(ip + 1, Mode::Immediate), value); self.write(self.read(ip + 1, Mode::Immediate), value);
ip += 2; ip += 2;
} }
Instruction::Output(mode) => { Instruction::Output(mode) => {
self.output.push(self.read(ip + 1, mode)); self.output.write(self.read(ip + 1, mode));
ip += 2; ip += 2;
} }
Instruction::JumpIfTrue(mode1, mode2) => { Instruction::JumpIfTrue(mode1, mode2) => {
@ -149,8 +175,8 @@ impl Computer {
} }
} }
pub fn output(&self) -> &[i32] { pub fn output(&self) -> i32 {
&self.output self.output.last_value()
} }
} }