Created
December 5, 2019 05:58
-
-
Save cloudrac3r/1b2995bd991628c8fa45ecabca7cec9f to your computer and use it in GitHub Desktop.
Advent of Code 2019 day 5 solution (both parts)
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
// @ts-check | |
const {read} = require("../util/read") | |
const outputQueue = [] | |
const stdinQueue = [] | |
function dataReceiver(data) { | |
const value = +data.toString() | |
if (stdinQueue.length) stdinQueue.shift()(value) | |
} | |
function listenForInput() { | |
process.stdin.on("data", dataReceiver) | |
} | |
function stopListeningForInput() { | |
process.stdin.removeListener("data", dataReceiver) | |
} | |
function waitForInput() { | |
return new Promise(resolve => { | |
process.stdout.write("input > ") | |
stdinQueue.push(resolve) | |
}) | |
} | |
function output(value) { | |
console.log(value) | |
outputQueue.push(value) | |
} | |
const opMap = new Map([ | |
[1, { // add | |
args: 3, | |
noTransformArgs: [2], | |
code: (tape, value1, value2, loc) => { | |
tape[loc] = value1 + value2 | |
return null | |
} | |
}], | |
[2, { // multiply | |
args: 3, | |
noTransformArgs: [2], | |
code: (tape, value1, value2, loc) => { | |
tape[loc] = value1 * value2 | |
return null | |
} | |
}], | |
[3, { // input | |
args: 1, | |
noTransformArgs: [0], | |
code: (tape, loc) => { | |
return waitForInput().then(input => { | |
tape[loc] = input | |
return null | |
}) | |
} | |
}], | |
[4, { // output | |
args: 1, | |
noTransformArgs: [0], | |
code: (tape, loc) => { | |
output(tape[loc]) | |
return null | |
} | |
}], | |
[5, { // jump if true | |
args: 2, | |
noTransformArgs: [], | |
code: (tape, condition, loc) => { | |
if (condition !== 0) return loc | |
else return null | |
} | |
}], | |
[6, { // jump if false | |
args: 2, | |
noTransformArgs: [], | |
code: (tape, condition, loc) => { | |
if (condition === 0) return loc | |
else return null | |
} | |
}], | |
[7, { // less than | |
args: 3, | |
noTransformArgs: [2], | |
code: (tape, value1, value2, loc) => { | |
if (value1 < value2) { | |
tape[loc] = 1 | |
} else { | |
tape[loc] = 0 | |
} | |
return null | |
} | |
}], | |
[8, { // equals | |
args: 3, | |
noTransformArgs: [2], | |
code: (tape, value1, value2, loc) => { | |
if (value1 === value2) { | |
tape[loc] = 1 | |
} else { | |
tape[loc] = 0 | |
} | |
return null | |
} | |
}], | |
[99, { // exit (handled elsewhere) | |
args: 0, | |
noTransformArgs: [], | |
code: () => { | |
process.stdin.removeListener("data", dataReceiver) | |
} | |
}] | |
]) | |
/** | |
* @param {number} pos | |
* @param {number[]} tape | |
*/ | |
async function runInstruction(pos, tape) { | |
// quit if broken | |
if (tape[pos] === undefined) throw new Error("Out of content!!!") | |
// organise | |
const inst = tape[pos++] | |
console.log("Inst:", inst) | |
// organise op | |
const opcode = inst % 100 | |
const op = opMap.get(opcode) | |
console.log("Opcode:", opcode) | |
const padInst = inst.toString().padStart(2+op.args, "0").slice(0, -2).split("").reverse().join("") | |
// organise & resolve params | |
let params = [] | |
for (let i = 0; i < op.args; i++) { | |
console.log("next arg:", i, padInst[i], tape[pos]) | |
if (padInst[i] == "1" || op.noTransformArgs.includes(i)) { // direct | |
params.push(tape[pos++]) | |
} else { // addressed | |
params.push(tape[tape[pos++]]) | |
} | |
} | |
console.log("Params:", params) | |
const newPos = await op.code(tape, ...params) | |
if (newPos !== null) pos = newPos | |
return {pos, done: opcode === 99} | |
} | |
async function runTape(tape) { | |
listenForInput() | |
let done = false | |
let pos = 0 | |
while (!done) { | |
({pos, done} = await runInstruction(pos, tape)) | |
} | |
stopListeningForInput() | |
return tape | |
} | |
async function runFile(file) { | |
let tape = read(file).firstLine().split(",").map(x => +x) | |
console.log("Input tape:", tape) | |
await runTape(tape) | |
console.log("Tape:", tape) | |
console.log("Output:", outputQueue) | |
const final = outputQueue.length ? ""+outputQueue.slice(-1)[0] : "" | |
console.log("Final output:", final) | |
return final | |
} | |
module.exports.runFile = runFile |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment