-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday7.ts
139 lines (129 loc) · 3.37 KB
/
day7.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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import * as fs from "fs"
function load(program: string) {
return fs.readFileSync(program, "utf8")
.split(",")
.map(l => parseInt(l))
}
const program = load("input-day7.txt")
//const program = [3, 15, 3, 16, 1002, 16, 10, 16, 1, 16, 15, 15, 4, 15, 99, 0, 0]
function thruster(input: number[]): number {
const out = compute(program, input)
return out[out.length - 1]
}
function thrusterChain(phases: number[]): number {
const p = phases.slice()
let out = thruster([p.shift(), 0])
while (p.length) {
out = thruster([p.shift(), out])
}
return out
}
const phases = [0, 1, 2, 3, 4]
const allPhases = permutate(phases)
const maxThrust = allPhases.reduce((acc, v) => {
return Math.max(acc, thrusterChain(v))
}, 0)
console.log(maxThrust)
function permutate(a: number[]): number[][] {
if (a.length == 1) {
return [a]
}
return Array(a.length).fill(0)
.map((_, i) => {
const c = a.slice()
return [c.splice(i, 1)[0], c] as const
})
.reduce((acc, [prefix, rest]) => {
permutate(rest)
.map(p => [prefix, ...p])
.forEach(p => acc.push(p))
return acc
}, [])
}
function compute(p: number[], input: number[]): number[] {
const mem = p.slice()
const outputs = []
let iptr = 0
while (true) {
const code = mem[iptr]
const op = code % 100
const modes = [code % 1000 / 100, code % 10000 / 1000, code % 100000 / 10000].map(Math.floor)
switch (op) {
case 1:
iptr = add(iptr, mem, modes)
break
case 2:
iptr = mul(iptr, mem, modes)
break
case 3:
iptr = get(iptr, mem, modes, input)
break
case 4:
const [newIptr, output] = put(iptr, mem, modes)
iptr = newIptr
//outputs.push(output)
return [output]
break
case 5:
iptr = jnz(iptr, mem, modes)
break
case 6:
iptr = jz(iptr, mem, modes)
break
case 7:
iptr = lt(iptr, mem, modes)
break
case 8:
iptr = eq(iptr, mem, modes)
break
case 99:
return outputs
default: throw new Error(`unknown instruction ${mem[iptr]}`)
}
}
}
function v(mem: number[], ptr: number, mode: number) {
if (mode === 0) {
return mem[mem[ptr]]
} else if (mode === 1) {
return mem[ptr]
}
throw new Error(`unknown mode ${mode}`)
}
function add(iptr: number, mem: number[], modes: number[]) {
mem[mem[iptr + 3]] = v(mem, iptr + 1, modes[0]) + v(mem, iptr + 2, modes[1])
return iptr + 4
}
function mul(iptr: number, mem: number[], modes: number[]) {
mem[mem[iptr + 3]] = v(mem, iptr + 1, modes[0]) * v(mem, iptr + 2, modes[1])
return iptr + 4
}
function put(iptr: number, mem: number[], modes: number[]) {
return [iptr + 2, v(mem, iptr + 1, modes[0])]
}
function get(iptr: number, mem: number[], modes: number[], input: number[]) {
mem[mem[iptr + 1]] = input.shift()
return iptr + 2
}
function jnz(iptr: number, mem: number[], modes: number[]) {
if (v(mem, iptr + 1, modes[0]) !== 0) {
return v(mem, iptr + 2, modes[1])
}
return iptr + 3
}
function jz(iptr: number, mem: number[], modes: number[]) {
if (v(mem, iptr + 1, modes[0]) === 0) {
return v(mem, iptr + 2, modes[1])
}
return iptr + 3
}
function lt(iptr: number, mem: number[], modes: number[]) {
const val = (v(mem, iptr + 1, modes[0]) < v(mem, iptr + 2, modes[1])) ? 1 : 0
mem[mem[iptr + 3]] = val
return iptr + 4
}
function eq(iptr: number, mem: number[], modes: number[]) {
const val = (v(mem, iptr + 1, modes[0]) === v(mem, iptr + 2, modes[1])) ? 1 : 0
mem[mem[iptr + 3]] = val
return iptr + 4
}