Skip to content

Instantly share code, notes, and snippets.

@svantelidman
Last active December 5, 2019 18:19
Show Gist options
  • Save svantelidman/10fe445629f95bb8a8c8aae61a48d09c to your computer and use it in GitHub Desktop.
Save svantelidman/10fe445629f95bb8a8c8aae61a48d09c to your computer and use it in GitHub Desktop.
use std::io::{self, BufReader, BufRead};
use std::env;
use std::fs::File;
fn main() {
let args: Vec<String> = env::args().collect();
let program_file = &args[1];
let mut loaded_program: Vec<i32> = load_program(program_file);
run_program(&mut loaded_program);
}
fn run_program(mut program: &mut Vec<i32>) -> i32 {
let mut prog_ptr:usize = 0;
loop {
let a = next_instruction(&mut prog_ptr, &mut program);
match a {
InstructionResult::Continue => {},
InstructionResult::Break => break,
_ => panic!("Unexpected action."),
}
}
program[0]
}
const ADD: i32 = 1;
const MULT: i32 = 2;
const INPUT: i32 = 3;
const OUTPUT: i32 = 4;
const JUMP_TRUE: i32 = 5;
const JUMP_FALSE: i32 = 6;
const LESS_THAN: i32 = 7;
const EQUALS: i32 = 8;
const BREAK: i32 = 99;
fn get_parameter_value(mode: i32, value: i32, program: &Vec<i32>) -> i32 {
if mode == 0 {
return program[value as usize]
} else if mode == 1 {
return value
} else {
panic!("Unknown parameter mode: {}", mode)
}
}
fn next_instruction(prog_ptr: &mut usize, program: &mut Vec<i32>) -> InstructionResult {
let next_instruction_code = next_cell(prog_ptr, program);
let next_op_code = next_instruction_code % 100;
let mode_par_1 = (next_instruction_code / 100) % 10;
let mode_par_2 = (next_instruction_code / 1000) % 10;
let mode_par_3 = (next_instruction_code / 10000) % 10;
match next_op_code {
ADD => {
let t1 = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let t2 = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
let store_at = next_cell(prog_ptr, program) as usize;
program[store_at] = t1 + t2;
InstructionResult::Continue
},
MULT => {
let f1 = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let f2 = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
let store_at = next_cell(prog_ptr, program) as usize;
program[store_at] = f1 * f2;
InstructionResult::Continue
},
INPUT => {
let store_at = next_cell(prog_ptr, program) as usize;
println!("INPUT>>");
let stdin = io::stdin();
let line = stdin.lock().lines().next().expect("Could not read from stdin");
let line = line.expect("No string there.");
let c = i32::from_str_radix(&line, 10).expect("Could not parse int");
program[store_at] = c;
InstructionResult::Continue
},
JUMP_TRUE => {
let value = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let jump_target = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
if value != 0 {
*prog_ptr = jump_target as usize
}
InstructionResult::Continue
},
JUMP_FALSE => {
let value = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let jump_target = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
if value == 0 {
*prog_ptr = jump_target as usize
}
InstructionResult::Continue
},
LESS_THAN => {
let p1 = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let p2 = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
let p3 = next_cell(prog_ptr, program);
let result = if p1 < p2 { 1 } else { 0 };
program[p3 as usize] = result;
InstructionResult::Continue
},
EQUALS => {
let p1 = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
let p2 = get_parameter_value(mode_par_2, next_cell(prog_ptr, program), program);
let p3 = next_cell(prog_ptr, program);
let result = if p1 == p2 { 1 } else { 0 };
program[p3 as usize] = result;
InstructionResult::Continue
},
OUTPUT => {
let v = get_parameter_value(mode_par_1, next_cell(prog_ptr, program), program);
println!("OUTPUT>>{}", v);
InstructionResult::Continue
},
BREAK => InstructionResult::Break,
_ => InstructionResult::Invalid
}
}
enum InstructionResult{
Continue,
Invalid,
Break
}
fn load_program(program_file: &String) -> Vec<i32> {
let mut prog: Vec<i32> = vec![];
let file = File::open(program_file).expect("Could not open program file!");
let reader = BufReader::new(file);
let line = reader.lines().next().expect("Could not read from stdin");
let line = line.expect("No string there.");
for s in line.split(",") {
let c = i32::from_str_radix(&s, 10).expect("Could not parse int");
prog.push(c);
}
prog
}
fn next_cell(prog_ptr: &mut usize, program: &Vec<i32>) -> i32 {
let ind = *prog_ptr;
*prog_ptr += 1;
program[ind]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment