Skip to content

Commit 5654427

Browse files
committed
day7-2
1 parent 3884666 commit 5654427

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed

day7-2.ts

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
import * as fs from "fs"
2+
3+
class Computer {
4+
5+
halted = false
6+
output = undefined
7+
8+
private mem: number[]
9+
private iptr = 0
10+
private nextOutput = undefined
11+
private inputs = []
12+
13+
constructor(program: number[]) {
14+
this.mem = program.slice()
15+
}
16+
17+
input(...n: number[]) {
18+
this.inputs = this.inputs.concat(n)
19+
return this
20+
}
21+
22+
compute() {
23+
if (this.halted) {
24+
throw new Error("computer already halted")
25+
}
26+
27+
while (true) {
28+
this.iptr = this.step()
29+
if (this.halted) {
30+
return { halted: true }
31+
}
32+
if (typeof this.nextOutput !== "undefined") {
33+
this.output = this.nextOutput
34+
this.nextOutput = undefined
35+
return { output: this.output }
36+
}
37+
}
38+
}
39+
40+
private step() {
41+
let iptr = this.iptr
42+
const mem = this.mem
43+
44+
const code = this.mem[iptr]
45+
const op = code % 100
46+
const modes = [code % 1000 / 100, code % 10000 / 1000, code % 100000 / 10000].map(Math.floor)
47+
48+
switch (op) {
49+
case 1: return add(iptr, mem, modes)
50+
case 2: return mul(iptr, mem, modes)
51+
case 3: return get(iptr, mem, modes, this.inputs)
52+
case 4:
53+
const [newIptr, output] = put(iptr, mem, modes)
54+
this.nextOutput = output
55+
return newIptr
56+
case 5: return jnz(iptr, mem, modes)
57+
case 6: return jz(iptr, mem, modes)
58+
case 7: return lt(iptr, mem, modes)
59+
case 8: return eq(iptr, mem, modes)
60+
case 99:
61+
this.halted = true
62+
return iptr
63+
default: throw new Error(`unknown instruction ${mem[iptr]}`)
64+
}
65+
}
66+
}
67+
68+
function load(program: string) {
69+
return fs.readFileSync(program, "utf8")
70+
.split(",")
71+
.map(l => parseInt(l))
72+
}
73+
74+
const program = load("input-day7.txt")
75+
76+
function thrusterChain(phases: number[]): number {
77+
const thrusters = phases.map(phase => new Computer(program).input(phase))
78+
thrusters[0].input(0)
79+
thrusters[0].compute()
80+
81+
while (true) {
82+
thrusters[1].input(thrusters[0].output).compute()
83+
thrusters[2].input(thrusters[1].output).compute()
84+
thrusters[3].input(thrusters[2].output).compute()
85+
thrusters[4].input(thrusters[3].output).compute()
86+
if (thrusters[4].halted) {
87+
return thrusters[4].output
88+
}
89+
thrusters[0].input(thrusters[4].output).compute()
90+
}
91+
}
92+
93+
const phases = [5, 6, 7, 8, 9]
94+
const allPhases = permutate(phases)
95+
const maxThrust = allPhases.reduce((acc, v) => {
96+
return Math.max(acc, thrusterChain(v))
97+
}, 0)
98+
console.log(maxThrust)
99+
100+
function permutate(a: number[]): number[][] {
101+
if (a.length == 1) {
102+
return [a]
103+
}
104+
return Array(a.length).fill(0)
105+
.map((_, i) => {
106+
const c = a.slice()
107+
return [c.splice(i, 1)[0], c] as const
108+
})
109+
.reduce((acc, [prefix, rest]) => {
110+
permutate(rest)
111+
.map(p => [prefix, ...p])
112+
.forEach(p => acc.push(p))
113+
return acc
114+
}, [])
115+
}
116+
117+
function v(mem: number[], ptr: number, mode: number) {
118+
if (mode === 0) {
119+
return mem[mem[ptr]]
120+
} else if (mode === 1) {
121+
return mem[ptr]
122+
}
123+
throw new Error(`unknown mode ${mode}`)
124+
}
125+
126+
function add(iptr: number, mem: number[], modes: number[]) {
127+
mem[mem[iptr + 3]] = v(mem, iptr + 1, modes[0]) + v(mem, iptr + 2, modes[1])
128+
return iptr + 4
129+
}
130+
function mul(iptr: number, mem: number[], modes: number[]) {
131+
mem[mem[iptr + 3]] = v(mem, iptr + 1, modes[0]) * v(mem, iptr + 2, modes[1])
132+
return iptr + 4
133+
}
134+
function put(iptr: number, mem: number[], modes: number[]) {
135+
return [iptr + 2, v(mem, iptr + 1, modes[0])]
136+
}
137+
function get(iptr: number, mem: number[], modes: number[], input: number[]) {
138+
if (input.length === 0) {
139+
throw new Error("no input")
140+
}
141+
mem[mem[iptr + 1]] = input.shift()
142+
return iptr + 2
143+
}
144+
function jnz(iptr: number, mem: number[], modes: number[]) {
145+
if (v(mem, iptr + 1, modes[0]) !== 0) {
146+
return v(mem, iptr + 2, modes[1])
147+
}
148+
return iptr + 3
149+
}
150+
function jz(iptr: number, mem: number[], modes: number[]) {
151+
if (v(mem, iptr + 1, modes[0]) === 0) {
152+
return v(mem, iptr + 2, modes[1])
153+
}
154+
return iptr + 3
155+
}
156+
function lt(iptr: number, mem: number[], modes: number[]) {
157+
const val = (v(mem, iptr + 1, modes[0]) < v(mem, iptr + 2, modes[1])) ? 1 : 0
158+
mem[mem[iptr + 3]] = val
159+
return iptr + 4
160+
}
161+
function eq(iptr: number, mem: number[], modes: number[]) {
162+
const val = (v(mem, iptr + 1, modes[0]) === v(mem, iptr + 2, modes[1])) ? 1 : 0
163+
mem[mem[iptr + 3]] = val
164+
return iptr + 4
165+
}

tsconfig.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES6"
4+
}
5+
}

0 commit comments

Comments
 (0)