-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathcomputer.js
94 lines (85 loc) · 1.68 KB
/
computer.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
class Computer {
constructor(input) {
this.raw_input = input.slice(0);
this.reset();
}
reset() {
this.program = this.parseInput(this.raw_input);
this.accu = 0;
this.instruction = 0;
this.record = {};
}
parseInput(input) {
return input.map((line) => {
let [, command, arg] = /(\w+) (.+)$/.exec(line);
arg = Number(arg);
return { command, arg };
});
}
acc(arg) {
this.accu += arg;
this.updateRecord();
this.instruction++;
}
jmp(arg) {
this.updateRecord();
this.instruction += arg;
}
nop() {
this.updateRecord();
this.instruction++;
}
updateRecord() {
if (!this.record[this.instruction]) {
this.record[this.instruction] = 0;
}
this.record[this.instruction]++;
}
getMaxRecord() {
let max = 0;
let counts = Object.values(this.record);
for (let count of counts) {
if (count > max) max = count;
}
return max;
}
runUntil2nd() {
let acc_before;
do {
let { command, arg } = this.program[this.instruction];
acc_before = this.accu;
this[command](arg);
} while (this.getMaxRecord() < 2);
return acc_before;
}
runUntilN(n) {
do {
let cmd = this.program[this.instruction];
if (!cmd) {
return this.accu;
}
let { command, arg } = cmd;
this[command](arg);
} while (this.getMaxRecord() < n);
return null;
}
tryChanges() {
this.reset();
for (let i = 0; i < this.program.length; i++) {
let cmd = this.program[i];
if (cmd.command === 'jmp') {
cmd.command = 'nop';
} else if (cmd.command === 'nop') {
cmd.command = 'jmp';
} else {
continue;
}
let val = this.runUntilN(2);
if (val !== null) {
return val;
}
this.reset();
}
}
}
module.exports = { Computer };