Created
December 22, 2018 01:59
-
-
Save jemmyw/020986286062ebc123a2b296ad13be9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as fs from 'fs'; | |
interface Opcodes { | |
[index: string]: (registers: number[], a: number, b: number) => number; | |
} | |
type Sample = [number[], number[], number[]]; | |
const opcodes: Opcodes = { | |
addr: (r, a, b) => r[a] + r[b], | |
addi: (r, a, b) => r[a] + b, | |
mulr: (r, a, b) => r[a] * r[b], | |
muli: (r, a, b) => r[a] * b, | |
banr: (r, a, b) => r[a] & r[b], | |
bani: (r, a, b) => r[a] & b, | |
borr: (r, a, b) => r[a] | r[b], | |
bori: (r, a, b) => r[a] | b, | |
setr: (r, a, b) => r[a], | |
seti: (r, a, b) => a, | |
gtir: (r, a, b) => (a > r[b] ? 1 : 0), | |
gtri: (r, a, b) => (r[a] > b ? 1 : 0), | |
gtrr: (r, a, b) => (r[a] > r[b] ? 1 : 0), | |
eqir: (r, a, b) => (a === r[b] ? 1 : 0), | |
eqri: (r, a, b) => (r[a] === b ? 1 : 0), | |
rqrr: (r, a, b) => (r[a] === r[b] ? 1 : 0), | |
}; | |
const opkeys = Object.keys(opcodes); | |
function registersEqual(r1: number[], r2: number[]) { | |
return r1.length === r2.length && r1.every((v, idx) => r2[idx] === v); | |
} | |
function applicable(before: number[], after: number[], instruction: number[]) { | |
const [i, a, b, c] = instruction; | |
return opkeys.filter(key => { | |
const r = before.slice(); | |
r[c] = opcodes[key](r, a, b); | |
return registersEqual(r, after); | |
}); | |
} | |
console.log([3, 2, 2, 1]); | |
console.log(applicable([3, 2, 1, 1], [3, 2, 2, 1], [9, 2, 1, 2])); | |
function registerLine(prefix: string, line: string): number[] | null { | |
const m = line.match(new RegExp(`^${prefix}: (.+)$`)); | |
if (m && m[1]) { | |
return JSON.parse(m[1]); | |
} | |
return null; | |
} | |
function instructionLine(line: string): number[] | null { | |
const m = line.match(/^(\d+) (\d+) (\d+) (\d+)$/); | |
if (m) { | |
return [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])]; | |
} | |
return null; | |
} | |
const samples: Sample[] = []; | |
fs.readFileSync('16.txt') | |
.toString() | |
.split('\n') | |
.reduce((acc: [number[], number[], number[]], line) => { | |
const before = registerLine('Before', line); | |
if (before) { | |
acc[0] = before; | |
return acc; | |
} | |
const after = registerLine('After', line); | |
if (after) { | |
acc[1] = after; | |
samples.push(acc); | |
return []; | |
} | |
const ins = instructionLine(line); | |
if (ins) { | |
acc[2] = ins; | |
return acc; | |
} | |
return []; | |
}, []); | |
const samplesMatchingThree = samples.reduce((acc: number, sample) => { | |
const codes = applicable(...sample); | |
if (codes.length >= 3) return acc + 1; | |
return acc; | |
}, 0); | |
console.log(samplesMatchingThree); | |
const codeMap = new Map<string, [Set<number>, Set<number>]>(); | |
opkeys.forEach(key => codeMap.set(key, [new Set(), new Set()])); | |
samples.forEach(sample => { | |
const i = sample[2][0]; | |
const codes = applicable(...sample); | |
opkeys.forEach(key => { | |
const map = codeMap.get(key); | |
if (codes.includes(key) && !map[1].has(i)) { | |
map[0].add(i); | |
} | |
if (!codes.includes(key)) { | |
map[0].delete(i); | |
map[1].add(i); | |
} | |
codeMap.set(key, map); | |
}); | |
}); | |
while (true) { | |
const withone = opkeys.filter(key => codeMap.get(key)[0].size === 1); | |
if (withone.length === opkeys.length) break; | |
withone.forEach(key => { | |
const map = codeMap.get(key); | |
if (map[0].size === 1) { | |
opkeys.forEach(otherKey => { | |
if (otherKey !== key) | |
codeMap.get(otherKey)[0].delete(map[0].values().next().value); | |
}); | |
} | |
}); | |
} | |
const codes = opkeys.reduce((acc: string[], key) => { | |
const code = codeMap | |
.get(key)[0] | |
.values() | |
.next().value; | |
acc[code] = key; | |
return acc; | |
}, []); | |
console.log(codes); | |
const program = fs | |
.readFileSync('16-2.txt') | |
.toString() | |
.split('\n') | |
.map(instructionLine); | |
function executeProgram(program: Array<number[]>): number[] { | |
return program.reduce( | |
(acc, ins) => { | |
const [i, a, b, c] = ins; | |
const opcode = codes[i]; | |
acc[c] = opcodes[opcode](acc, a, b); | |
return acc; | |
}, | |
[0, 0, 0, 0] | |
); | |
} | |
const registers = executeProgram(program); | |
console.log(registers); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment