Skip to content

Instantly share code, notes, and snippets.

@jemmyw
Created December 22, 2018 01:59
Show Gist options
  • Save jemmyw/020986286062ebc123a2b296ad13be9b to your computer and use it in GitHub Desktop.
Save jemmyw/020986286062ebc123a2b296ad13be9b to your computer and use it in GitHub Desktop.
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