-
Notifications
You must be signed in to change notification settings - Fork 16
/
program.js
114 lines (93 loc) · 3.24 KB
/
program.js
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const assert = require('assert');
const LINE_RE = /^([a-z]+) (inc|dec) (-?\d+) if ([a-z]+) ([!<>=]+) (-?\d+)$/;
class Instruction {
constructor(line) {
let program = this.parse(line);
this.reg = program.reg;
this.op = program.op;
this.reg_amount = program.reg_amount;
this.cond_reg = program.cond_reg;
this.comp = program.comp;
this.cond_amount = program.cond_amount;
}
parse(line) {
//c dec -10 if a >= 1
assert.strictEqual(LINE_RE.test(line), true);
let [match, reg, op, reg_amount, cond_reg, comp, cond_amount] = LINE_RE.exec(line);
reg_amount = parseInt(reg_amount);
cond_amount = parseInt(cond_amount);
return { reg, op, reg_amount, cond_reg, comp, cond_amount };
}
}
const EQ = '==';
const NE = '!=';
const GT = '>';
const GE = '>=';
const LT = '<';
const LE = '<=';
const INCREMENT = 'inc';
const DECREMENT = 'dec';
class Program {
constructor(instructions) {
this.registers = {};
this.instructions = instructions.map(i => {
let instruction = new Instruction(i);
this.registers[instruction.reg] = 0;
this.registers[instruction.cond_reg] = 0;
return instruction;
});
}
executeLine(line) {
let { reg, comp, cond_reg, cond_amount } = line;
let conditional;
if (comp === EQ) {
conditional = this.registers[cond_reg] === cond_amount;
} else if (comp === NE) {
conditional = this.registers[cond_reg] !== cond_amount;
} else if (comp === GT) {
conditional = this.registers[cond_reg] > cond_amount;
} else if (comp === GE) {
conditional = this.registers[cond_reg] >= cond_amount;
} else if (comp === LT) {
conditional = this.registers[cond_reg] < cond_amount;
} else if (comp === LE) {
conditional = this.registers[cond_reg] <= cond_amount;
} else {
let error = `Unknown conditional comparison operator: "${comp}"`;
console.error(line);
throw error;
}
if (conditional) {
let { op, reg_amount } = line;
if (op === INCREMENT) {
this.registers[reg] += reg_amount;
} else if (op === DECREMENT) {
this.registers[reg] -= reg_amount;
} else {
let error = `Unknown binary operator: "${op}"`;
console.error(line);
throw error;
}
}
return this.registers[reg];
}
executeAndGetLargestRegister() {
this.instructions.forEach(instruction => {
this.executeLine(instruction);
});
return Math.max(...Object.values(this.registers));
}
executeAndGetLargestRegisterAtAnyTime() {
let largest = Number.MIN_SAFE_INTEGER;
this.instructions.forEach(instruction => {
this.executeLine(instruction);
let { reg, cond_reg } = instruction;
let temp_max = Math.max(this.registers[reg], this.registers[cond_reg]);
if (temp_max > largest) {
largest = temp_max;
}
});
return largest;
}
}
module.exports = Program;