-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathintCodeComputer.js
More file actions
111 lines (100 loc) · 3.75 KB
/
intCodeComputer.js
File metadata and controls
111 lines (100 loc) · 3.75 KB
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
class IntCodeComputer {
constructor(input) {
this.relativeBase = 0;
this.intCode = toIntCode(input);
this.pointer = 0;
this.executeInstruction = function (opCode3Input) {
const opCode = getOpCode(this.intCode[this.pointer]);
const rawInstruction = this.intCode[this.pointer].toString();
const [param1, param2, param3] = this.intCode.slice(this.pointer + 1, this.pointer + 4);
const param1Mode = +rawInstruction[rawInstruction.length - 3] || 0;
const param2Mode = +rawInstruction[rawInstruction.length - 4] || 0;
const param3Mode = +rawInstruction[rawInstruction.length - 5] || 0;
const [param1Val, param2Val, param3Val] = [
this.getParamValue(param1Mode, param1),
this.getParamValue(param2Mode, param2),
this.getParamAddress(param3Mode, param3)
];
switch (opCode) {
case 1:
case 2:
this.intCode[param3Val] = addOrMultiply(opCode, param1Val, param2Val);
this.pointer += 4;
return null;
case 3:
const inputTargetAddr = this.getParamAddress(param1Mode, param1);
this.intCode[inputTargetAddr] = opCode3Input;
this.pointer += 2;
return null;
case 4:
this.pointer += 2;
return param1Val;
case 5:
this.pointer = param1Val !== 0 ? param2Val : (this.pointer + 3);
return null;
case 6:
this.pointer = param1Val === 0 ? param2Val : (this.pointer + 3);
return null;
case 7:
this.intCode[param3Val] = param1Val < param2Val ? 1 : 0;
this.pointer += 4;
return null;
case 8:
this.intCode[param3Val] = param1Val === param2Val ? 1 : 0;
this.pointer += 4;
return null;
case 9:
this.relativeBase += param1Val;
this.pointer += 2;
return null;
default:
throw `Unsupported opCode: ${opCode}`;
}
};
this.getParamValue = function (paramMode, param) {
switch (paramMode) {
case 0:
return this.intCode[param] || 0;
case 1:
return param;
case 2:
return this.intCode[this.relativeBase + param] || 0;
default:
throw ("Unsupported param mode");
}
}
this.getParamAddress = function (paramMode, param) {
switch (paramMode) {
case 0:
return param;
case 1:
throw ("Unsupported address mode");
case 2:
return this.relativeBase + param;
default:
throw ("Unsupported address mode");
}
}
}
get mustHalt() {
return this.intCode[this.pointer] === 99;
}
get opCode() {
return getOpCode(this.intCode[this.pointer]);
}
}
function addOrMultiply(opCode, param1, param2) {
return opCode === 1
? param1 + param2
: param1 * param2;
}
function getOpCode(instruction) {
const instrString = instruction.toString();
return instrString.length < 3
? instruction
: +instrString[instrString.length - 1];
}
function toIntCode(input) {
return input.split(',').map(x => +x);
}
module.exports = IntCodeComputer;