diff --git a/d23.lua b/d23.lua new file mode 100644 index 0000000..f8c0115 --- /dev/null +++ b/d23.lua @@ -0,0 +1,189 @@ +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() + +network = {} +for i = 1, 50 do + computer = {mem={table.unpack(program)}, inp={i - 1}, outp={}} + computer.input = input_array(computer.inp) + computer.output = output_array(computer.outp) + table.insert(network, computer) +end + +nat_seen = {} +nat = nil +while true do + running = false + idle = true + for _, computer in ipairs(network) do + if #computer.inp == 0 then + table.insert(computer.inp, -1) + else + idle = false + end + if interpret(computer) then + running = true + end + while #computer.outp > 0 do + addr = table.remove(computer.outp, 1) + x = table.remove(computer.outp, 1) + y = table.remove(computer.outp, 1) + if addr == 255 then + if not nat then + print("Part 1:", y) + end + nat = {x, y} + else + dest = network[addr + 1] + table.insert(dest.inp, x) + table.insert(dest.inp, y) + end + end + end + if idle then + if nat_seen[nat[2]] then + print("Part 2:", nat[2]) + break + end + nat_seen[nat[2]] = true + table.insert(network[1].inp, nat[1]) + table.insert(network[1].inp, nat[2]) + end + if not running then + break + end +end diff --git a/d23_input.txt b/d23_input.txt new file mode 100644 index 0000000..c4a1f1c --- /dev/null +++ b/d23_input.txt @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2239,105,1,0,1326,825,1367,1827,1091,1157,2208,986,2132,2070,629,763,1895,1569,1431,1235,1264,1198,1126,1602,1761,1660,600,2023,1295,699,1862,1534,1021,854,571,1631,1697,1396,1058,1994,916,668,1965,2171,1730,1928,1466,2101,730,947,885,1501,794,1796,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1106,0,73,3,65,20101,0,64,1,21002,66,1,2,21102,105,1,0,1106,0,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,133,1,133,68,133,101,0,0,62,1001,133,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,0,1,0,1001,161,1,169,101,0,65,0,1102,1,1,61,1102,0,1,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1106,0,178,21101,210,0,0,105,1,69,2101,0,1,70,1101,0,0,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1106,0,218,1105,1,73,109,4,21102,0,1,-3,21101,0,0,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1105,1,263,22102,1,-3,-3,109,-4,2106,0,0,109,4,21102,1,1,-3,21102,1,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,22101,0,-3,-3,109,-4,2106,0,0,109,1,101,1,68,359,20101,0,0,1,101,3,68,367,20102,1,0,2,21101,0,376,0,1106,0,436,22102,1,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21101,0,0,-4,21102,1,0,-3,21101,51,0,-2,21201,-2,-1,-2,1201,-2,385,470,21002,0,1,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1105,1,547,21102,1,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1106,0,529,21202,-4,1,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2106,0,0,1101,22651,0,66,1102,1,1,67,1101,598,0,68,1102,1,556,69,1102,1,0,71,1101,0,600,72,1106,0,73,1,1985,1101,0,89681,66,1101,1,0,67,1102,1,627,68,1102,556,1,69,1101,0,0,71,1102,1,629,72,1105,1,73,1,1851,1101,0,35977,66,1102,1,5,67,1101,0,656,68,1101,0,253,69,1102,1,1,71,1102,1,666,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,13,12487,1101,80683,0,66,1102,1,1,67,1102,1,695,68,1102,1,556,69,1101,1,0,71,1101,697,0,72,1105,1,73,1,160,5,266043,1101,0,11071,66,1102,1,1,67,1102,726,1,68,1102,1,556,69,1101,1,0,71,1101,728,0,72,1105,1,73,1,16183,33,66161,1102,1,22073,66,1102,1,1,67,1102,1,757,68,1101,0,556,69,1102,1,2,71,1102,1,759,72,1106,0,73,1,-3,3,185578,42,136954,1101,23971,0,66,1102,1,1,67,1101,790,0,68,1102,1,556,69,1102,1,1,71,1102,792,1,72,1106,0,73,1,125,21,47643,1101,55291,0,66,1101,0,1,67,1102,821,1,68,1102,1,556,69,1101,0,1,71,1101,0,823,72,1106,0,73,1,29443,3,278367,1101,0,18457,66,1102,1,1,67,1101,852,0,68,1102,556,1,69,1102,1,0,71,1101,0,854,72,1105,1,73,1,1347,1101,0,84061,66,1102,1,1,67,1101,881,0,68,1102,556,1,69,1101,1,0,71,1101,0,883,72,1105,1,73,1,1277,8,253588,1102,94399,1,66,1102,1,1,67,1101,0,912,68,1102,1,556,69,1101,1,0,71,1102,914,1,72,1105,1,73,1,761,8,126794,1102,95869,1,66,1101,0,1,67,1102,943,1,68,1101,0,556,69,1101,0,1,71,1102,1,945,72,1106,0,73,1,271,8,63397,1101,66553,0,66,1102,1,5,67,1101,0,974,68,1102,1,302,69,1102,1,1,71,1101,984,0,72,1105,1,73,0,0,0,0,0,0,0,0,0,0,39,287932,1102,1,69779,66,1101,3,0,67,1101,1013,0,68,1102,1,302,69,1102,1,1,71,1102,1,1019,72,1106,0,73,0,0,0,0,0,0,45,66553,1101,89783,0,66,1101,0,4,67,1102,1048,1,68,1101,0,302,69,1101,1,0,71,1102,1056,1,72,1106,0,73,0,0,0,0,0,0,0,0,10,71954,1101,38891,0,66,1101,1,0,67,1102,1085,1,68,1101,556,0,69,1102,2,1,71,1102,1087,1,72,1106,0,73,1,67,45,266212,17,200542,1101,0,76091,66,1102,1,3,67,1102,1,1118,68,1101,302,0,69,1102,1,1,71,1102,1,1124,72,1105,1,73,0,0,0,0,0,0,39,143966,1102,16493,1,66,1101,0,1,67,1102,1,1153,68,1101,0,556,69,1101,0,1,71,1101,1155,0,72,1105,1,73,1,-162,17,100271,1102,88681,1,66,1102,1,6,67,1101,0,1184,68,1102,302,1,69,1102,1,1,71,1102,1196,1,72,1105,1,73,0,0,0,0,0,0,0,0,0,0,0,0,12,195742,1101,0,100271,66,1101,0,4,67,1102,1225,1,68,1101,0,302,69,1102,1,1,71,1102,1,1233,72,1105,1,73,0,0,0,0,0,0,0,0,4,152182,1101,0,25453,66,1101,1,0,67,1102,1262,1,68,1102,556,1,69,1101,0,0,71,1102,1,1264,72,1105,1,73,1,1724,1102,7393,1,66,1101,1,0,67,1101,1291,0,68,1102,556,1,69,1101,1,0,71,1102,1293,1,72,1106,0,73,1,333706,47,16334,1101,0,75479,66,1101,0,1,67,1102,1322,1,68,1101,0,556,69,1102,1,1,71,1102,1324,1,72,1105,1,73,1,21,33,198483,1102,1,79967,66,1102,1,1,67,1101,1353,0,68,1101,0,556,69,1101,0,6,71,1101,1355,0,72,1106,0,73,1,17335,26,23369,4,76091,4,228273,14,59399,14,118798,14,178197,1101,24251,0,66,1102,1,1,67,1101,1394,0,68,1102,556,1,69,1101,0,0,71,1102,1,1396,72,1105,1,73,1,1093,1101,0,66161,66,1101,3,0,67,1101,1423,0,68,1101,0,302,69,1102,1,1,71,1101,1429,0,72,1105,1,73,0,0,0,0,0,0,10,143908,1102,1,59399,66,1102,1,3,67,1102,1458,1,68,1101,0,302,69,1102,1,1,71,1101,0,1464,72,1105,1,73,0,0,0,0,0,0,39,71983,1102,68477,1,66,1102,1,3,67,1101,1493,0,68,1101,0,302,69,1101,1,0,71,1102,1,1499,72,1106,0,73,0,0,0,0,0,0,10,179885,1101,0,8167,66,1101,2,0,67,1102,1528,1,68,1101,302,0,69,1102,1,1,71,1102,1,1532,72,1105,1,73,0,0,0,0,10,35977,1102,65393,1,66,1102,1,1,67,1101,0,1561,68,1102,1,556,69,1101,0,3,71,1102,1,1563,72,1105,1,73,1,5,21,15881,21,31762,5,88681,1101,0,12487,66,1102,1,2,67,1101,0,1596,68,1101,302,0,69,1102,1,1,71,1102,1600,1,72,1105,1,73,0,0,0,0,7,139558,1101,0,13553,66,1101,1,0,67,1101,1629,0,68,1101,0,556,69,1101,0,0,71,1102,1,1631,72,1106,0,73,1,1602,1101,49877,0,66,1101,0,1,67,1101,0,1658,68,1102,1,556,69,1102,0,1,71,1101,0,1660,72,1106,0,73,1,1807,1101,15881,0,66,1101,0,4,67,1102,1687,1,68,1101,302,0,69,1102,1,1,71,1102,1695,1,72,1105,1,73,0,0,0,0,0,0,0,0,5,177362,1101,47059,0,66,1102,1,1,67,1101,1724,0,68,1101,556,0,69,1102,1,2,71,1102,1726,1,72,1105,1,73,1,10,21,63524,5,532086,1102,1,102967,66,1102,1,1,67,1101,1757,0,68,1102,1,556,69,1102,1,1,71,1101,0,1759,72,1105,1,73,1,54,13,24974,1102,1,7369,66,1102,1,1,67,1102,1788,1,68,1101,556,0,69,1101,3,0,71,1101,0,1790,72,1105,1,73,1,3,7,69779,45,133106,17,401084,1102,1,42797,66,1102,1,1,67,1102,1823,1,68,1101,0,556,69,1102,1,1,71,1101,0,1825,72,1105,1,73,1,446,28,89783,1101,0,92789,66,1101,0,3,67,1102,1854,1,68,1101,302,0,69,1101,0,1,71,1102,1,1860,72,1106,0,73,0,0,0,0,0,0,10,107931,1101,0,23369,66,1102,2,1,67,1101,1889,0,68,1102,302,1,69,1102,1,1,71,1102,1,1893,72,1105,1,73,0,0,0,0,39,215949,1102,1,97871,66,1101,2,0,67,1102,1,1922,68,1101,351,0,69,1101,0,1,71,1101,0,1926,72,1105,1,73,0,0,0,0,255,79967,1102,23167,1,66,1102,1,1,67,1102,1,1955,68,1101,0,556,69,1101,4,0,71,1101,0,1957,72,1105,1,73,1,1,3,92789,42,205431,33,132322,17,300813,1101,0,103993,66,1101,1,0,67,1102,1992,1,68,1101,0,556,69,1101,0,0,71,1101,1994,0,72,1105,1,73,1,1403,1102,1,21157,66,1101,0,1,67,1101,0,2021,68,1102,1,556,69,1101,0,0,71,1101,0,2023,72,1106,0,73,1,1512,1102,19583,1,66,1102,1,1,67,1102,2050,1,68,1102,556,1,69,1101,9,0,71,1102,2052,1,72,1105,1,73,1,2,28,269349,28,359132,47,8167,7,209337,45,199659,8,190191,8,316985,5,354724,5,443405,1101,77479,0,66,1101,1,0,67,1102,2097,1,68,1102,556,1,69,1102,1,1,71,1101,0,2099,72,1105,1,73,1,13,45,332765,1102,1,35393,66,1102,1,1,67,1102,1,2128,68,1102,1,556,69,1101,1,0,71,1101,2130,0,72,1105,1,73,1,211,28,179566,1101,63397,0,66,1102,5,1,67,1101,2159,0,68,1101,302,0,69,1101,1,0,71,1102,1,2169,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,26,46738,1101,0,71983,66,1102,1,4,67,1101,2198,0,68,1102,253,1,69,1102,1,1,71,1101,0,2206,72,1105,1,73,0,0,0,0,0,0,0,0,12,97871,1102,64063,1,66,1102,1,1,67,1102,1,2235,68,1102,1,556,69,1101,0,1,71,1101,0,2237,72,1106,0,73,1,42487,42,68477