Last active
December 18, 2019 04:34
-
-
Save FelicitusNeko/8849eec36c142e13d8468cab7d7a0c78 to your computer and use it in GitHub Desktop.
Advent of Code 2019 Day 9
This file contains hidden or 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
| // Day 9 part 2 is literally the exact same code except the input is 2 instead of 1 | |
| class IntOpcodeMachine { | |
| constructor(pgm) { | |
| this.pgm = pgm.split(',').map(i => parseInt(i)); | |
| this.originalPgm = this.pgm.slice(0); | |
| this.position = 0; | |
| this.relBase = 0; | |
| this.cmdSize = { 1: 4, 2: 4, 3: 2, 4: 2, 5: 3, 6: 3, 7: 4, 8: 4, 9: 2, 99: 1 } | |
| this.input = []; this.output = []; | |
| } | |
| run() { | |
| let isRunning = true; | |
| let retval = true; | |
| let runCount = 0; | |
| while (isRunning && this.position < this.pgm.length) { | |
| let noun = 0, verb = 0; | |
| let opcode = this.pgm[this.position] % 100; | |
| if (this.cmdSize[opcode] === undefined) throw new Error(`Invalid opcode ${opcode} at position ${this.position}`); | |
| let mode = []; | |
| for (let x = 2; x <= this.cmdSize[opcode]; x++) mode.push(Math.round(this.pgm[this.position] / Math.pow(10, x)) % 10); | |
| switch (opcode) { | |
| case 1: // Add values | |
| noun = this.getWithMode(this.position + 1, mode[0]); | |
| verb = this.getWithMode(this.position + 2, mode[1]); | |
| this.setWithMode(this.position + 3, mode[2], noun + verb); | |
| break; | |
| case 2: // Multiply values | |
| noun = this.getWithMode(this.position + 1, mode[0]); | |
| verb = this.getWithMode(this.position + 2, mode[1]); | |
| this.setWithMode(this.position + 3, mode[2], noun * verb); | |
| break; | |
| case 3: // Get from input stack | |
| if (this.input.length === 0) return false; | |
| this.setWithMode(this.position + 1, mode[0], this.input.shift()); | |
| break; | |
| case 4: // Push to output stack | |
| this.output.push(this.getWithMode(this.position + 1, mode[0])); | |
| break; | |
| case 5: // Jump if true | |
| if (this.getWithMode(this.position + 1, mode[0]) !== 0) this.position = this.getWithMode(this.position + 2, mode[1]) - 3; | |
| break; | |
| case 6: // Jump if false | |
| if (this.getWithMode(this.position + 1, mode[0]) === 0) this.position = this.getWithMode(this.position + 2, mode[1]) - 3; | |
| break; | |
| case 7: // Evaluate less than | |
| this.setWithMode(this.position + 3, mode[2], (this.getWithMode(this.position + 1, mode[0]) < this.getWithMode(this.position + 2, mode[1]) ? 1 : 0)); | |
| break; | |
| case 8: // Evaluate equal | |
| this.setWithMode(this.position + 3, mode[2], (this.getWithMode(this.position + 1, mode[0]) === this.getWithMode(this.position + 2, mode[1]) ? 1 : 0)); | |
| break; | |
| case 9: // Adjust relative base | |
| this.relBase += this.getWithMode(this.position + 1, mode[0]); | |
| break; | |
| case 99: // End program | |
| isRunning = false; break; | |
| default: throw new Error(`Invalid opcode ${opcode} at position ${this.position}`); | |
| } | |
| this.position += this.cmdSize[opcode]; | |
| if (runCount > 50000) { | |
| console.debug(this.output); | |
| console.debug(this.toString()); | |
| throw new Error('Run length cap exceeded'); | |
| } | |
| } | |
| console.debug(this.pgm); | |
| return retval; | |
| } | |
| addInput(data) { | |
| if (Array.isArray(data)) this.input = this.input.concat(data); | |
| else this.input.push(data); | |
| } | |
| getOutput() { return this.output.shift(); } | |
| getAllOutput() { | |
| let retval = this.output; | |
| this.output = []; | |
| return retval; | |
| } | |
| zeroFillToPos(pos) { | |
| while (this.pgm.length <= pos) this.pgm.push(0); | |
| } | |
| setAt(pos, data) { | |
| this.zeroFillToPos(pos); | |
| this.pgm[pos] = data; | |
| } | |
| getAt(pos) { | |
| this.zeroFillToPos(pos); | |
| return this.pgm[pos]; | |
| } | |
| getModePos(pos, mode) { | |
| switch (mode) { | |
| case 0: return this.pgm[pos]; | |
| case 1: return pos; | |
| case 2: return this.pgm[pos] + this.relBase; | |
| default: throw new Error(`Invalid access mode #${mode}`); | |
| } | |
| } | |
| setWithMode(pos, mode, data) { | |
| let modePos = this.getModePos(pos, mode); | |
| this.zeroFillToPos(modePos); | |
| this.pgm[modePos] = data; | |
| } | |
| getWithMode(pos, mode) { | |
| let modePos = this.getModePos(pos, mode); | |
| this.zeroFillToPos(modePos); | |
| return this.pgm[modePos]; | |
| } | |
| goto(pos) { this.position = pos; } | |
| restart() { this.pgm = this.originalPgm.slice(); this.position = 0; this.input = []; this.output = []; } | |
| toString() { return this.pgm.join(','); } | |
| } | |
| let testMachine = [ | |
| new IntOpcodeMachine('109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99'), | |
| new IntOpcodeMachine('1102,34915192,34915192,7,4,7,99,0'), | |
| new IntOpcodeMachine('104,1125899906842624,99') | |
| ]; | |
| testMachine.forEach((i, x) => { | |
| i.run(); | |
| console.debug(`Machine #${x} output:`, i.getAllOutput()); | |
| }); | |
| let bigData = '1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,32,1016,1102,326,1,1029,1102,1,26,1009,1102,1,753,1024,1102,1,1,1021,1102,35,1,1000,1102,1,0,1020,1101,25,0,1012,1102,36,1,1011,1101,0,33,1013,1102,1,667,1022,1102,1,38,1014,1102,1,24,1017,1101,0,31,1004,1102,443,1,1026,1101,37,0,1015,1101,27,0,1007,1101,0,748,1025,1102,1,23,1008,1102,1,34,1002,1101,28,0,1006,1102,1,22,1003,1101,0,29,1005,1101,0,39,1018,1101,21,0,1019,1102,30,1,1001,1102,660,1,1023,1102,1,331,1028,1101,0,440,1027,1101,0,20,1010,109,18,1206,2,195,4,187,1105,1,199,1001,64,1,64,1002,64,2,64,109,-12,1208,0,28,63,1005,63,217,4,205,1105,1,221,1001,64,1,64,1002,64,2,64,109,3,2101,0,-5,63,1008,63,31,63,1005,63,247,4,227,1001,64,1,64,1106,0,247,1002,64,2,64,109,-7,2101,0,6,63,1008,63,26,63,1005,63,267,1105,1,273,4,253,1001,64,1,64,1002,64,2,64,109,10,21108,40,40,4,1005,1016,295,4,279,1001,64,1,64,1106,0,295,1002,64,2,64,109,-9,2107,23,0,63,1005,63,315,1001,64,1,64,1105,1,317,4,301,1002,64,2,64,109,30,2106,0,-5,4,323,1105,1,335,1001,64,1,64,1002,64,2,64,109,-19,1202,-9,1,63,1008,63,26,63,1005,63,355,1106,0,361,4,341,1001,64,1,64,1002,64,2,64,109,-5,21107,41,42,6,1005,1015,379,4,367,1105,1,383,1001,64,1,64,1002,64,2,64,109,-6,21108,42,43,8,1005,1011,403,1001,64,1,64,1105,1,405,4,389,1002,64,2,64,109,11,21102,43,1,1,1008,1015,42,63,1005,63,425,1106,0,431,4,411,1001,64,1,64,1002,64,2,64,109,13,2106,0,0,1105,1,449,4,437,1001,64,1,64,1002,64,2,64,109,1,1205,-7,463,4,455,1106,0,467,1001,64,1,64,1002,64,2,64,109,-14,1206,7,479,1105,1,485,4,473,1001,64,1,64,1002,64,2,64,109,-6,1202,0,1,63,1008,63,23,63,1005,63,507,4,491,1106,0,511,1001,64,1,64,1002,64,2,64,109,13,1205,-1,523,1106,0,529,4,517,1001,64,1,64,1002,64,2,64,109,-23,2107,22,10,63,1005,63,551,4,535,1001,64,1,64,1106,0,551,1002,64,2,64,109,14,21101,44,0,6,1008,1018,44,63,1005,63,577,4,557,1001,64,1,64,1106,0,577,1002,64,2,64,109,-12,2108,32,0,63,1005,63,597,1001,64,1,64,1105,1,599,4,583,1002,64,2,64,109,7,1201,-4,0,63,1008,63,20,63,1005,63,619,1106,0,625,4,605,1001,64,1,64,1002,64,2,64,109,-11,1201,6,0,63,1008,63,34,63,1005,63,647,4,631,1106,0,651,1001,64,1,64,1002,64,2,64,109,20,2105,1,7,1001,64,1,64,1106,0,669,4,657,1002,64,2,64,109,-4,21101,45,0,6,1008,1018,46,63,1005,63,689,1106,0,695,4,675,1001,64,1,64,1002,64,2,64,109,-16,2108,22,7,63,1005,63,717,4,701,1001,64,1,64,1105,1,717,1002,64,2,64,109,10,1207,0,27,63,1005,63,733,1105,1,739,4,723,1001,64,1,64,1002,64,2,64,109,8,2105,1,10,4,745,1105,1,757,1001,64,1,64,1002,64,2,64,109,1,21102,46,1,-2,1008,1013,46,63,1005,63,779,4,763,1106,0,783,1001,64,1,64,1002,64,2,64,109,-2,1208,-7,29,63,1005,63,799,1105,1,805,4,789,1001,64,1,64,1002,64,2,64,109,-19,2102,1,10,63,1008,63,32,63,1005,63,829,1001,64,1,64,1106,0,831,4,811,1002,64,2,64,109,14,1207,-2,29,63,1005,63,849,4,837,1105,1,853,1001,64,1,64,1002,64,2,64,109,8,21107,47,46,-6,1005,1010,873,1001,64,1,64,1106,0,875,4,859,1002,64,2,64,109,-17,2102,1,6,63,1008,63,29,63,1005,63,901,4,881,1001,64,1,64,1106,0,901,4,64,99,21102,1,27,1,21102,1,915,0,1106,0,922,21201,1,27817,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,0,942,0,1105,1,922,21202,1,1,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0'; | |
| let finalMachine = new IntOpcodeMachine(bigData); | |
| finalMachine.addInput(1); | |
| finalMachine.run(); | |
| console.log('Final output', finalMachine.getAllOutput()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment