From 14fc01d1272523a1651142c734a3cb4c26534f2c Mon Sep 17 00:00:00 2001 From: mid-kid Date: Tue, 17 Dec 2019 23:23:52 +0100 Subject: [PATCH] Add day 17 --- d17.lua | 263 ++++++++++++++++++++++++++++++++++++++++++++++++++ d17_input.txt | 1 + d17_path.txt | 5 + 3 files changed, 269 insertions(+) create mode 100644 d17.lua create mode 100644 d17_input.txt create mode 100644 d17_path.txt diff --git a/d17.lua b/d17.lua new file mode 100644 index 0000000..27b2371 --- /dev/null +++ b/d17.lua @@ -0,0 +1,263 @@ +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) + +map = {} +line = {} +interpret({mem={table.unpack(program)}, output=function(val) + local val = string.char(val) + if val == "\n" then + table.insert(map, line) + line = {} + else + table.insert(line, val) + end +end}) + +part1 = 0 +for y = 2, #map - 1 do + for x = 2, #map[y] - 1 do + if map[y][x] == "#" and map[y-1][x] == "#" and map[y][x+1] == "#" and map[y+1][x] == "#" and map[y][x-1] == "#" then + part1 = part1 + (y-1) * (x-1) + end + end +end +print("Part 1:", part1) + +pos = nil +for y = 1, #map do + for x = 1, #map[y] do + if map[y][x] == "^" then + pos = {y=y, x=x} + break + end + end + if pos then + break + end +end + +function get_nextpos(pos, direction) + if direction == "^" then + next_pos = {y=pos.y - 1, x=pos.x} + elseif direction == ">" then + next_pos = {y=pos.y, x=pos.x + 1} + elseif direction == "v" then + next_pos = {y=pos.y + 1, x=pos.x} + elseif direction == "<" then + next_pos = {y=pos.y, x=pos.x - 1} + end + return next_pos +end + +path = {} +distance = 0 +direction = "^" +while true do + next_pos = get_nextpos(pos, direction) + + if map[next_pos.y] and map[next_pos.y][next_pos.x] == "#" then + distance = distance + 1 + pos = next_pos + else + if distance ~= 0 then + table.insert(path, distance) + distance = 0 + end + + if direction == "^" then + dir_l = "<" + dir_r = ">" + elseif direction == ">" then + dir_l = "^" + dir_r = "v" + elseif direction == "v" then + dir_l = ">" + dir_r = "<" + elseif direction == "<" then + dir_l = "v" + dir_r = "^" + end + + pos_l = get_nextpos(pos, dir_l) + pos_r = get_nextpos(pos, dir_r) + + if map[pos_l.y] and map[pos_l.y][pos_l.x] == "#" then + table.insert(path, "L") + direction = dir_l + elseif map[pos_r.y] and map[pos_r.y][pos_r.x] == "#" then + table.insert(path, "R") + direction = dir_r + else + break + end + end +end + +print(table.concat(path, ",")) +print("Compress the path manually you lazy fuck") + +function sleep(s) + local ntime = os.clock() + s + repeat until os.clock() >= ntime +end + +-- Flushing doesn't work as expected... oh well +io.stdout:flush() +io.stdout:setvbuf("full", 0x10000) + +program_p2 = {table.unpack(program)} +program_p2[1] = 2 +last_output = 0 +interpret({mem=program_p2, output=function(val) + if val >= 0x80 then + io.stdout:write(val) + io.stdout:write("\n") + else + if last_output == 10 and val == 10 then + io.stdout:flush() + sleep(0.1) + end + last_output = val + io.stdout:write(string.char(val)) + end +end, input=function() + io.stdout:flush() + return string.byte(io.stdin:read(1)) +end}) diff --git a/d17_input.txt b/d17_input.txt new file mode 100644 index 0000000..1e208df --- /dev/null +++ b/d17_input.txt @@ -0,0 +1 @@ +1,330,331,332,109,3762,1101,1182,0,16,1101,0,1467,24,101,0,0,570,1006,570,36,101,0,571,0,1001,570,-1,570,1001,24,1,24,1105,1,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21102,58,1,0,1105,1,786,1006,332,62,99,21101,0,333,1,21102,1,73,0,1106,0,579,1101,0,0,572,1102,1,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,102,1,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1106,0,81,21101,0,340,1,1106,0,177,21102,477,1,1,1105,1,177,21101,0,514,1,21102,1,176,0,1106,0,579,99,21102,1,184,0,1105,1,579,4,574,104,10,99,1007,573,22,570,1006,570,165,101,0,572,1182,21101,0,375,1,21102,1,211,0,1106,0,579,21101,1182,11,1,21101,0,222,0,1106,0,979,21102,388,1,1,21101,0,233,0,1105,1,579,21101,1182,22,1,21102,1,244,0,1105,1,979,21101,401,0,1,21101,0,255,0,1105,1,579,21101,1182,33,1,21101,266,0,0,1105,1,979,21101,0,414,1,21101,277,0,0,1105,1,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,1182,0,1,21102,1,313,0,1105,1,622,1005,575,327,1101,0,1,575,21102,1,327,0,1105,1,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,0,8,0,109,4,2102,1,-3,587,20102,1,0,-1,22101,1,-3,-3,21101,0,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,1201,-4,0,630,20102,1,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,653,20101,0,0,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21102,702,1,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21102,1,731,0,1106,0,786,1105,1,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21101,0,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21102,1,774,0,1106,0,622,21201,-3,1,-3,1106,0,640,109,-5,2105,1,0,109,7,1005,575,802,20101,0,576,-6,20101,0,577,-5,1106,0,814,21102,0,1,-1,21101,0,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21101,1,0,-1,1106,0,924,1205,-2,873,21101,35,0,-4,1106,0,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,1,2,0,2102,1,-3,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21002,0,1,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,51,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1102,1,1,575,21101,973,0,0,1105,1,786,99,109,-7,2106,0,0,109,6,21102,1,0,-4,21102,0,1,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1105,1,1041,21101,-4,0,-2,1106,0,1041,21101,0,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,2101,0,-2,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,2101,0,-2,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1106,0,1150,21102,1,477,1,1106,0,1150,21102,514,1,1,21102,1149,1,0,1105,1,579,99,21102,1157,1,0,1105,1,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1201,-5,0,1176,2101,0,-4,0,109,-6,2105,1,0,12,13,32,1,11,1,32,1,5,9,30,1,5,1,5,1,1,1,30,1,5,1,5,1,1,1,30,1,5,1,5,1,1,1,30,1,5,1,5,1,1,1,30,1,5,1,5,1,1,1,18,13,5,7,1,1,44,1,44,1,44,1,44,1,1,1,42,1,1,1,42,9,38,1,5,1,38,1,5,1,38,1,5,1,38,1,5,1,38,1,5,1,36,7,1,1,36,1,1,1,3,1,1,1,36,1,1,1,3,1,1,1,36,1,1,1,3,1,1,1,36,1,1,9,34,1,5,1,1,1,1,1,34,9,1,1,40,1,3,1,32,9,3,1,32,1,11,1,32,1,11,1,1,7,24,1,11,1,1,1,5,1,16,5,3,1,11,1,1,1,5,1,16,1,3,1,3,1,11,1,1,1,5,1,16,1,3,1,3,1,9,9,1,1,16,1,3,1,3,1,9,1,1,1,1,1,3,1,1,1,16,9,9,1,1,9,20,1,13,1,3,1,3,1,22,1,13,1,3,5,22,1,13,1,30,9,5,1,38,1,5,1,36,9,36,1,1,1,40,9,36,1,1,1,1,1,3,1,36,1,1,1,1,1,3,1,36,1,1,1,1,1,3,1,36,5,3,1,38,1,5,1,38,7,12 diff --git a/d17_path.txt b/d17_path.txt new file mode 100644 index 0000000..50f394e --- /dev/null +++ b/d17_path.txt @@ -0,0 +1,5 @@ +R,12,L,8,R,12,R,8,R,6,R,6,R,8,R,12,L,8,R,12,R,8,R,6,R,6,R,8,R,8,L,8,R,8,R,4,R,4,R,8,L,8,R,8,R,4,R,4,R,8,R,6,R,6,R,8,R,8,L,8,R,8,R,4,R,4,R,8,R,6,R,6,R,8,R,12,L,8,R,12 +A = R,12,L,8,R,12 +B = R,8,R,6,R,6,R,8 +C = R,8,L,8,R,8,R,4,R,4 +A,B,A,B,C,C,B,C,B,A