Skip to content

Instantly share code, notes, and snippets.

@dpeek
Created December 5, 2019 14:44
Show Gist options
  • Save dpeek/c7cfda72353f0998a5ee33e47585ab17 to your computer and use it in GitHub Desktop.
Save dpeek/c7cfda72353f0998a5ee33e47585ab17 to your computer and use it in GitHub Desktop.
const opcode = op => {
const str = String(op);
return parseInt(str.substr(str.length - 2));
};
const mode = (op, pos) => {
const str = String(op);
if (pos + 2 > str.length) return 0;
return parseInt(str.substr(str.length - (2 + pos), 1));
};
const param = (memory, pos, num) => {
const op = memory[pos];
const value = memory[pos + num];
return mode(op, num) === 0 ? memory[value] : value;
};
const tick = (pos, memory, input, ram, debug = false) => {
const op = opcode(memory[pos]);
const p1 = param(memory, pos, 1);
const p2 = param(memory, pos, 2);
const p3 = param(memory, pos, 3);
let to;
switch (op) {
case 1: // add
to = memory[pos + 3];
if (debug) console.log(`ADD: [${to}] = ${p1} + ${p2}`);
memory[to] = p1 + p2;
return pos + 4;
case 2: // multiply
to = memory[pos + 3];
if (debug) console.log(`MUL: [${to}] = ${p1} * ${p2}`);
memory[to] = p1 * p2;
return pos + 4;
case 3: // input
to = memory[pos + 1];
if (debug) console.log(`INP: [${to}] = ${input}`);
memory[to] = input;
return pos + 2;
case 4: // output
ram.output = p1;
return pos + 2;
case 5: // jump-if-true
to = p2; //memory[pos + 2];
if (debug) console.log(`IFT: ${p1} !== 0 => ${p1 !== 0}`);
if (p1 !== 0) {
if (debug) console.log(`JMP: [${to}]`);
return to;
}
return pos + 3;
case 6: // jump-if-false
to = p2; //memory[pos + 2];
if (debug) console.log(`IFT: ${p1} === 0 => ${p1 === 0}`);
if (p1 === 0) {
if (debug) console.log(`JMP: [${to}]`);
return to;
}
return pos + 3;
case 7: // less than
to = memory[pos + 3];
if (debug) {
console.log(`ILT: ${p1} < ${p2} => ${p1 < p2}`);
console.log(`[${to}] = ${p1 < p2 ? 1 : 0}`);
}
memory[to] = p1 < p2 ? 1 : 0;
return pos + 4;
case 8: // equals
to = memory[pos + 3];
if (debug) {
console.log(`IEQ ${p1} === ${p2} => ${p1 === p2}`);
console.log(`[${to}] = ${p1 === p2 ? 1 : 0}`);
}
memory[to] = p1 === p2 ? 1 : 0;
return pos + 4;
case 99: // halt
if (debug) console.log("HLT");
return -1;
default:
console.log(`unknown opcode ${op}`);
return -1;
}
};
const run = (program, input, debug = false) => {
const ram = {};
const memory = program.split(",").map(str => parseInt(str, 10));
let pos = 0;
while (pos > -1) pos = tick(pos, memory, input, ram, debug);
return ram.output;
};
const tests = [
{
name:
"Using position mode, consider whether the input is equal to 8; output 1 (if it is) or 0 (if it is not).",
program: "3,9,8,9,10,9,4,9,99,-1,8",
cases: [
{ input: 8, output: 1 },
{ input: 9, output: 0 }
]
},
{
name:
"Using position mode, consider whether the input is less than 8; output 1 (if it is) or 0 (if it is not).",
program: "3,9,7,9,10,9,4,9,99,-1,8",
cases: [
{ input: 7, output: 1 },
{ input: 8, output: 0 }
]
},
{
name:
"Using immediate mode, consider whether the input is equal to 8; output 1 (if it is) or 0 (if it is not).",
program: "3,3,1108,-1,8,3,4,3,99",
cases: [
{ input: 8, output: 1 },
{ input: 9, output: 0 }
]
},
{
name:
"Using immediate mode, consider whether the input is less than 8; output 1 (if it is) or 0 (if it is not).",
program: "3,3,1107,-1,8,3,4,3,99",
cases: [
{ input: 7, output: 1 },
{ input: 8, output: 0 }
]
},
{
name:
"Using position mode, take an input, then output 0 if the input was zero or 1 if the input was non-zero.",
program: "3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9",
cases: [
{ input: 0, output: 0 },
{ input: 2, output: 1 }
]
},
{
name:
"Using immediate mode, take an input, then output 0 if the input was zero or 1 if the input was non-zero.",
program: "3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9",
cases: [
{ input: 0, output: 0 },
{ input: 2, output: 1 }
]
},
{
name:
"Outputs 999 if the input value is below 8, output 1000 if the input value is equal to 8, or output 1001 if the input value is greater than 8.",
program:
"3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99",
cases: [
{ input: 4, output: 999 },
{ input: 8, output: 1000 },
{ input: 10, output: 1001 }
]
}
];
tests.forEach(test => {
let pass = true;
test.cases.forEach(({ input, output }) => {
const actual = run(test.program, input);
if (actual !== output) {
pass = false;
console.log("Fail: " + test.name);
console.log(`Output was ${actual} should be ${output}`);
}
});
console.log("Pass: " + test.name);
});
const program = require("fs")
.readFileSync("./05.txt")
.toString();
console.log(run(program, 1));
console.log(run(program, 5));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment