diff --git a/d09.lua b/d09.lua new file mode 100644 index 0000000..b1fbd0f --- /dev/null +++ b/d09.lua @@ -0,0 +1,139 @@ +function get_param(state, arg) + local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10 + if #state.mem < state.pos + arg then + print(string.format("Error: Opcode too short at end of memory: %d", state.pos)) + os.exit(false) + end + local arg = state.mem[state.pos + arg] + if param_mode == 0 then + arg = arg + 1 + elseif param_mode == 2 then + arg = arg + state.relbase + end + return arg +end + +function read_mem(state, arg) + local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10 + local arg = get_param(state, arg) + if param_mode == 1 then + return arg + end + arg = state.mem[arg] + if not arg then + return 0 + end + return arg +end + +function write_mem(state, arg, val) + local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10 + local arg = get_param(state, arg) + if param_mode == 1 then + print(string.format("Error: Invalid inmediate write: %d", arg)) + end + state.mem[arg] = val +end + +function interpret(state) + if not state.mem then + state.mem = state + end + if not state.pos then + state.pos = 1 + state.relbase = 1 + end + if not state.input then + state.input = input_stdin + end + if not state.output then + state.output = output_stdout + end + + while true do + if #state.mem < state.pos then + print(string.format("Instruction pointer ran off of memory")) + os.exit(false) + end + + local opcode = state.mem[state.pos] % 100 + local instr_size = 1 + + if opcode == 1 then + write_mem(state, 3, read_mem(state, 1) + read_mem(state, 2)) + instr_size = 4 + elseif opcode == 2 then + write_mem(state, 3, read_mem(state, 1) * read_mem(state, 2)) + instr_size = 4 + elseif opcode == 3 then + local val = state.input() + if not val then return true end + write_mem(state, 1, val) + instr_size = 2 + elseif opcode == 4 then + state.output(read_mem(state, 1)) + instr_size = 2 + elseif opcode == 5 then + instr_size = 3 + if read_mem(state, 1) ~= 0 then + state.pos = read_mem(state, 2) + 1 + instr_size = 0 + end + elseif opcode == 6 then + instr_size = 3 + if read_mem(state, 1) == 0 then + state.pos = read_mem(state, 2) + 1 + instr_size = 0 + end + elseif opcode == 7 then + write_mem(state, 3, read_mem(state, 1) < read_mem(state, 2) and 1 or 0) + instr_size = 4 + elseif opcode == 8 then + write_mem(state, 3, read_mem(state, 1) == read_mem(state, 2) and 1 or 0) + instr_size = 4 + elseif opcode == 9 then + state.relbase = state.relbase + read_mem(state, 1) + instr_size = 2 + elseif opcode == 99 then + return false + else + print(string.format("Error: Invalid opcode %d at %d", opcode, state.pos - 1)) + os.exit(false) + end + + state.pos = state.pos + instr_size + end +end + +function input_stdin() + io.stdout:write("> ") + return io.stdin:read("n") +end + +function output_stdout(val) + io.stdout:write(val) + io.stdout:write("\n") +end + +function input_array(array) + function inner() + return table.remove(array, 1) + end + return inner +end + +function output_array(array) + function inner(val) + table.insert(array, val) + end + return inner +end + +file = io.open(arg[1]) +program = {} +for num in string.gmatch(file:read(), "(-?%d+),?") do + table.insert(program, tonumber(num)) +end +file:close() + +interpret(program) diff --git a/d09_input.txt b/d09_input.txt new file mode 100644 index 0000000..e3fc113 --- /dev/null +++ b/d09_input.txt @@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,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,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-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