-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
112 lines (89 loc) · 2.54 KB
/
index.ts
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
enum InstructionCodes {
acc = "acc",
jmp = "jmp",
nop = "nop",
}
interface Instruction {
code: InstructionCodes;
argument: number;
}
interface RAM {
acc: number;
pointer: number;
log: number[];
error: boolean;
}
const parseInstruction = (instruction: string): Instruction => {
const [code, argument] = instruction.split(" ");
return { code: code as InstructionCodes, argument: parseInt(argument, 10) };
};
const runBootInstructions = (instructions: Instruction[]): RAM => {
const RAM: RAM = {
acc: 0,
pointer: 0,
log: [],
error: false,
};
while (true) {
// Exit when infinite loop
if (RAM.log.includes(RAM.pointer)) {
RAM.error = true;
break;
}
// Exit when trying to run an instruction out of range
else if (RAM.pointer >= instructions.length) {
break;
}
const { code, argument } = instructions[RAM.pointer];
RAM.log.push(RAM.pointer);
if (code === InstructionCodes.acc) {
RAM.acc += argument;
} else if (code === InstructionCodes.jmp) {
RAM.pointer += argument;
continue;
} else if (code === InstructionCodes.nop) {
}
RAM.pointer += 1;
}
return RAM;
};
export const part1 = (input: string) => {
const instructions: Instruction[] = input.split("\n").map(parseInstruction);
const { acc } = runBootInstructions(instructions);
return acc;
};
const getNextExecution = (
instructions: Instruction[],
latestChangedIndex: number
) => {
let _instructions: Instruction[] = instructions.slice();
for (let i = latestChangedIndex + 1; i <= _instructions.length; i++) {
if (_instructions[i].code === InstructionCodes.nop) {
_instructions[i] = { ..._instructions[i], code: InstructionCodes.jmp };
return {
instructions: _instructions,
latestChangedIndex: i,
};
} else if (_instructions[i].code === InstructionCodes.jmp) {
_instructions[i] = { ..._instructions[i], code: InstructionCodes.nop };
return {
instructions: _instructions,
latestChangedIndex: i,
};
}
}
throw new Error("Program cannot be fixed");
};
export const part2 = (input: string) => {
const instructions: Instruction[] = input.split("\n").map(parseInstruction);
let nextExecution = getNextExecution(instructions, 0);
let RAM = runBootInstructions(nextExecution.instructions);
while (RAM.error) {
nextExecution = getNextExecution(
instructions,
nextExecution.latestChangedIndex
);
RAM = runBootInstructions(nextExecution.instructions);
}
return RAM.acc;
};