From c6226208a4e00d346b35cd7043a48d65bb7779ef Mon Sep 17 00:00:00 2001 From: mid-kid Date: Thu, 19 Dec 2019 11:56:40 +0100 Subject: [PATCH] Add day 19 --- d19.lua | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ d19_input.txt | 1 + 2 files changed, 245 insertions(+) create mode 100644 d19.lua create mode 100644 d19_input.txt diff --git a/d19.lua b/d19.lua new file mode 100644 index 0000000..83c324d --- /dev/null +++ b/d19.lua @@ -0,0 +1,244 @@ +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) + +--file = {} +--for line in io.lines(arg[1]) do + --fline = {} + --for char in line:gmatch(".") do + --if char == "." then + --table.insert(fline, 0) + --else + --table.insert(fline, 1) + --end + --end + --table.insert(file, fline) +--end + +result_p1 = 0 +angles_low = {} +angles_high = {} +for y = 0, 49 do +--for y = 0, 34 do + current = 0 + for x = 0, 49 do + --for x = 0, 34 do + output = {} + interpret({mem={table.unpack(program)}, input=input_array({x, y}), output=output_array(output)}) + --output = {file[y + 1][x + 1]} + result_p1 = result_p1 + output[1] + if current ~= output[1] then + current = output[1] + if current == 1 then + table.insert(angles_low, math.atan(y + 0.5, x + 0.5)) + else + table.insert(angles_high, math.atan(y + 0.5, x + 0.5)) + end + end + end +end +print("Part 1:", result_p1) + +p1 = {x=1, y=1} +p2 = {x=1, y=1} + +while (p2.x - p1.x) < 99 or (p1.y - p2.y) < 99 do + if (p2.x - p1.x) < 99 then + p2.x = p1.x + 99 + while true do + output = {} + interpret({mem={table.unpack(program)}, input=input_array({p2.x, p2.y}), output=output_array(output)}) + if output[1] == 1 then + break + end + p2.y = p2.y + 1 + end + end + if (p1.y - p2.y) < 99 then + p1.y = p2.y + 99 + while true do + output = {} + interpret({mem={table.unpack(program)}, input=input_array({p1.x, p1.y}), output=output_array(output)}) + if output[1] == 1 then + break + end + p1.x = p1.x + 1 + end + end +end + +print("Part 2:", p1.x * 10000 + p2.y) + + +-- I tried to do this using the law of cosines and it works for the example, but not for the "real" thing... + +function mean(table) + local sum = 0 + for _, x in ipairs(table) do + sum = sum + x + end + return sum / #table +end + +angle_low = mean(angles_low) +angle_high = mean(angles_high) +angle_rect = -math.pi * 1 / 4 + +print(angle_low, angle_high, angle_rect) + +angle_alpha = angle_low - angle_high +angle_beta = math.pi - (angle_low - angle_rect) +angle_gamma = angle_high - angle_rect + +print(angle_alpha, angle_beta, angle_gamma, (angle_alpha + angle_beta + angle_gamma) / math.pi) + +length_a = math.sqrt((99 ^ 2) + (99 ^ 2)) +--length_a = math.sqrt((9 ^ 2) + (9 ^ 2)) +length_b = length_a * math.sin(angle_beta) / math.sin(angle_alpha) +length_c = length_a * math.sin(angle_gamma) / math.sin(angle_alpha) + +pos_low = {x=math.cos(angle_low) * length_c, y=math.sin(angle_low) * length_c} +pos_high = {x=math.cos(angle_high) * length_b, y=math.sin(angle_high) * length_b} +print(pos_low.x, pos_low.y, pos_high.x, pos_high.y) +print(angle_rect + math.pi, math.atan(pos_low.y - pos_high.y, pos_low.x - pos_high.x)) + +pos_x = math.ceil(pos_low.x - 0.5) +pos_y = math.ceil(pos_high.y - 0.5) + +print("Part 2:", pos_x * 10000 + pos_y) diff --git a/d19_input.txt b/d19_input.txt new file mode 100644 index 0000000..669809d --- /dev/null +++ b/d19_input.txt @@ -0,0 +1 @@ +109,424,203,1,21102,11,1,0,1106,0,282,21102,18,1,0,1105,1,259,1202,1,1,221,203,1,21102,31,1,0,1106,0,282,21101,38,0,0,1106,0,259,21002,23,1,2,22102,1,1,3,21102,1,1,1,21102,1,57,0,1105,1,303,2101,0,1,222,21002,221,1,3,20101,0,221,2,21101,0,259,1,21102,1,80,0,1105,1,225,21102,1,8,2,21101,91,0,0,1106,0,303,1202,1,1,223,21002,222,1,4,21102,1,259,3,21101,225,0,2,21101,225,0,1,21101,0,118,0,1105,1,225,21001,222,0,3,21101,0,48,2,21102,133,1,0,1106,0,303,21202,1,-1,1,22001,223,1,1,21102,1,148,0,1105,1,259,1201,1,0,223,20101,0,221,4,21001,222,0,3,21101,0,6,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,105,1,108,20207,1,223,2,21001,23,0,1,21101,-1,0,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2101,0,-4,249,21201,-3,0,1,22102,1,-2,2,21202,-1,1,3,21102,1,250,0,1106,0,225,21201,1,0,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,22101,0,-2,-2,109,-3,2106,0,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,22101,0,-4,1,21101,384,0,0,1106,0,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,21201,1,0,-4,109,-5,2106,0,0