-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconsole.rs
95 lines (79 loc) · 1.78 KB
/
console.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::io;
use std::io::BufRead as _;
use std::vec::Vec;
enum Opcode {
nop,
acc,
jmp,
}
struct Instruction {
pub op: Opcode,
pub no: isize,
}
impl Instruction {
pub fn new(line: &str) -> Self {
let mut split = line.split(' ');
let opcode = match split.next().unwrap() {
"nop" => Opcode::nop,
"acc" => Opcode::acc,
"jmp" => Opcode::jmp,
_ => panic!("Unknown opcode"),
};
let arg: isize = split.next().unwrap().parse().unwrap();
return Self {
op: opcode,
no: arg,
};
}
}
struct Console {
instructions: Vec<Instruction>,
iptr: isize,
accu: isize,
}
impl Console {
pub fn new<T>(reader: T) -> Self
where T: io::Read
{
let mut instructions: Vec<Instruction> = vec![];
for line in io::BufReader::new(reader).lines() {
instructions.push(Instruction::new(&line.unwrap()));
}
return Console {
instructions,
iptr: 0,
accu: 0,
};
}
pub fn run(&mut self) {
let max = (self.instructions.len() as isize)- 1;
let mut executed: Vec<bool> = vec![];
for i in 0..=max { executed.push(false); }
while (self.iptr >= 0) && (self.iptr <= max) {
if executed[self.iptr as usize] {
println!("Visited instruction #{} again, accumulator is {}", self.iptr, self.accu);
return;
} else {
executed[self.iptr as usize] = true;
}
let i = &self.instructions[self.iptr as usize];
match i.op {
Opcode::nop => self.op_nop(i.no),
Opcode::acc => self.op_acc(i.no),
Opcode::jmp => self.op_jmp(i.no),
}
self.iptr += 1;
}
println!("Program terminated (iptr: {}), accumulator is {}", self.iptr, self.accu);
}
fn op_nop(&mut self, _arg: isize) { }
fn op_acc(&mut self, arg: isize) {
self.accu += arg;
}
fn op_jmp(&mut self, arg: isize) {
self.iptr += arg - 1;
}
}
fn main() {
Console::new(io::stdin()).run();
}