Browse Source

Better io support for intcode

master
parent
commit
50efed4686
  1. 23
      src/intcode/icio.rs
  2. 38
      src/intcode/mod.rs
  3. 30
      src/intcode/ops.rs

23
src/intcode/icio.rs

@ -0,0 +1,23 @@
use std::io;
pub trait IntCodeIO {
fn get(&mut self) -> isize;
fn put(&mut self, value: isize);
}
pub struct StdAdapter;
impl IntCodeIO for StdAdapter {
fn get(&mut self) -> isize {
let mut value = String::new();
let _ = io::stdin()
.read_line(&mut value)
.expect("Unable to read stdin");
value.trim().parse().unwrap()
}
fn put(&mut self, value: isize) {
println!("{}", value);
}
}

38
src/intcode/mod.rs

@ -1,9 +1,13 @@
mod ops;
mod icio;
pub struct IntCode {
pub use icio::{IntCodeIO, StdAdapter};
pub struct IntCode<I: IntCodeIO> {
addr_ptr: usize,
memory: Vec<isize>,
running: bool,
io: I
}
pub struct Value {
@ -11,10 +15,10 @@ pub struct Value {
address: Option<usize>,
}
struct Op {
struct Op<I: IntCodeIO> {
argc: u8,
argv: Vec<Value>,
function: OpCodeFn,
function: OpCodeFn<I>,
}
enum ParamMode {
@ -22,7 +26,7 @@ enum ParamMode {
Imediate
}
type OpCodeFn = fn(&mut IntCode, &Vec<Value>);
type OpCodeFn<I> = fn(&mut IntCode<I>, &Vec<Value>);
impl ParamMode {
fn from_int(mode: usize) -> Self {
@ -34,17 +38,29 @@ impl ParamMode {
}
}
impl IntCode {
impl IntCode<StdAdapter> {
#[cfg(test)]
pub fn from_vec(v: Vec<isize>) -> Self {
Self::from_vec_io(v, StdAdapter)
}
pub fn from_str(s: &str) -> Self {
Self::from_str_io(s, StdAdapter)
}
}
impl<I: IntCodeIO> IntCode<I> {
pub fn from_vec_io(v: Vec<isize>, io: I) -> Self {
IntCode {
memory: v,
addr_ptr: 0,
running: true,
io
}
}
pub fn from_str(s: &str) -> Self {
Self::from_vec(s.trim().split(",").filter_map(|n| n.parse().ok()).collect())
pub fn from_str_io(s: &str, io: I) -> Self {
Self::from_vec_io(s.trim().split(",").filter_map(|n| n.parse().ok()).collect(), io)
}
fn get_op_modes(&mut self) -> (u8, Vec<ParamMode>) {
@ -91,8 +107,8 @@ impl IntCode {
}
}
impl Op {
fn from_intcode(intcode: &mut IntCode) -> Self {
impl<I: IntCodeIO> Op<I> {
fn from_intcode(intcode: &mut IntCode<I>) -> Self {
let (code, vmodes) = intcode.get_op_modes();
let mut op = Op::from_code(code);
for idx in 0..(op.argc) {
@ -124,7 +140,7 @@ impl Op {
}
}
fn new(argc: u8, function: OpCodeFn) -> Self {
fn new(argc: u8, function: OpCodeFn<I>) -> Self {
Op {
argc,
argv: Vec::new(),
@ -132,7 +148,7 @@ impl Op {
}
}
fn run(&self, mut intcode: &mut IntCode) {
fn run(&self, mut intcode: &mut IntCode<I>) {
(self.function)(&mut intcode, &self.argv)
}
}

30
src/intcode/ops.rs

@ -1,50 +1,46 @@
use super::{Value, IntCode};
use std::io;
use super::{Value, IntCode, IntCodeIO};
pub fn add(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn add<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
intcode.write(argv[2].address.unwrap(), argv[0].value + argv[1].value);
}
pub fn mul(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn mul<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
intcode.write(argv[2].address.unwrap(), argv[0].value * argv[1].value);
}
pub fn exit(intcode: &mut IntCode, _argv: &Vec<Value>) {
pub fn exit<I: IntCodeIO>(intcode: &mut IntCode<I>, _argv: &Vec<Value>) {
intcode.terminate();
}
pub fn cin(intcode: &mut IntCode, argv: &Vec<Value>) {
let mut value = String::new();
let _ = io::stdin()
.read_line(&mut value)
.expect("Unable to read stdin");
intcode.write(argv[0].address.unwrap(), value.trim().parse().unwrap());
pub fn cin<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
let value = intcode.io.get();
intcode.write(argv[0].address.unwrap(), value);
}
pub fn cout(_intcode: &mut IntCode, argv: &Vec<Value>) {
println!("{}", argv[0].value);
pub fn cout<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
intcode.io.put(argv[0].value)
}
pub fn jump_if_true(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn jump_if_true<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
if argv[0].value != 0 {
intcode.jump(argv[1].value as usize)
}
}
pub fn jump_if_false(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn jump_if_false<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
if argv[0].value == 0 {
intcode.jump(argv[1].value as usize)
}
}
pub fn lt(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn lt<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
intcode.write(
argv[2].address.unwrap(),
if argv[0].value < argv[1].value { 1 } else { 0 }
);
}
pub fn eq(intcode: &mut IntCode, argv: &Vec<Value>) {
pub fn eq<I: IntCodeIO>(intcode: &mut IntCode<I>, argv: &Vec<Value>) {
intcode.write(
argv[2].address.unwrap(),
if argv[0].value == argv[1].value { 1 } else { 0 }

Loading…
Cancel
Save