diff --git a/d07.lua b/d07.lua new file mode 100644 index 0000000..f418bff --- /dev/null +++ b/d07.lua @@ -0,0 +1,193 @@ +function get_arg(mem, pos, arg) + local param_mode = mem[pos] // (10 ^ (arg + 1)) % 10 + if #mem < pos + arg then + print(string.format("Error: Opcode too short at end of memory: %d", pos)) + os.exit(false) + end + local arg = mem[pos + arg] + if param_mode == 0 then + arg = arg + 1 + if #mem < arg then + print(string.format("Error: Memory offset out of bounds: %d", arg)) + os.exit(false) + end + end + return arg +end + +function get_param(mem, pos, arg) + local param_mode = mem[pos] // (10 ^ (arg + 1)) % 10 + local arg = get_arg(mem, pos, arg) + if param_mode == 0 then + return mem[arg] + end + return arg +end + +function interpret(mem, state, input_func, output_func) + if not state.pos then + state.pos = 1 + end + + local pos = state.pos + while true do + if #mem < pos then + print(string.format("Instruction pointer ran off of memory")) + os.exit(false) + end + + local opcode = mem[pos] % 100 + + if opcode == 1 then + mem[get_arg(mem, pos, 3)] = get_param(mem, pos, 1) + get_param(mem, pos, 2) + pos = pos + 4 + elseif opcode == 2 then + mem[get_arg(mem, pos, 3)] = get_param(mem, pos, 1) * get_param(mem, pos, 2) + pos = pos + 4 + elseif opcode == 3 then + local val = input_func() + if not val then + state.pos = pos + return true + end + mem[get_arg(mem, pos, 1)] = val + pos = pos + 2 + elseif opcode == 4 then + output_func(get_param(mem, pos, 1)) + pos = pos + 2 + elseif opcode == 5 then + if get_param(mem, pos, 1) ~= 0 then + pos = get_param(mem, pos, 2) + 1 + else + pos = pos + 3 + end + elseif opcode == 6 then + if get_param(mem, pos, 1) == 0 then + pos = get_param(mem, pos, 2) + 1 + else + pos = pos + 3 + end + elseif opcode == 7 then + mem[get_arg(mem, pos, 3)] = get_param(mem, pos, 1) < get_param(mem, pos, 2) and 1 or 0 + pos = pos + 4 + elseif opcode == 8 then + mem[get_arg(mem, pos, 3)] = get_param(mem, pos, 1) == get_param(mem, pos, 2) and 1 or 0 + pos = pos + 4 + elseif opcode == 99 then + state.pos = pos + return false + else + print(string.format("Error: Invalid opcode %d at %d", opcode, pos - 1)) + os.exit(false) + end + 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() + +function get_signal(phase) + signal = 0 + for i = 1, 5 do + memory = {table.unpack(program)} + output = {} + interpret(memory, {}, input_array({phase[i], signal}), output_array(output)) + signal = output[1] + end + return signal +end + +function get_signal_p2(phase) + machines = {} + for i = 1, 5 do + if i == 1 then + input = {} + else + input = machines[i - 1].output + end + table.insert(input, phase[i] + 5) + machines[i] = {mem={table.unpack(program)}, input=input, output={}} + end + machines[5].output = machines[1].input + table.insert(machines[1].input, 0) + + while true do + done = true + for i = 1, 5 do + if interpret(machines[i].mem, machines[i], input_array(machines[i].input), output_array(machines[i].output)) then + done = false + end + end + if done then + break + end + end + return machines[5].output[1] +end + +biggest = 0 +biggest_p2 = 0 +for i = 0, (5 ^ 5) - 1 do + phase = { + i // (5 ^ 4) % 5, + i // (5 ^ 3) % 5, + i // (5 ^ 2) % 5, + i // (5 ^ 1) % 5, + i // (5 ^ 0) % 5 + } + count = {} + for _, x in ipairs(phase) do + if not count[x] then + count[x] = 0 + end + count[x] = count[x] + 1 + end + double = false + for _, x in pairs(count) do + if x > 1 then + double = true + end + end + + if not double then + signal = get_signal(phase) + if signal > biggest then + biggest = signal + end + signal = get_signal_p2(phase) + if signal > biggest_p2 then + biggest_p2 = signal + end + end +end + +print("Part 1:", biggest) +print("Part 2:", biggest_p2) diff --git a/d07_input.txt b/d07_input.txt new file mode 100644 index 0000000..52d6c9b --- /dev/null +++ b/d07_input.txt @@ -0,0 +1 @@ +3,8,1001,8,10,8,105,1,0,0,21,46,55,72,85,110,191,272,353,434,99999,3,9,1002,9,5,9,1001,9,2,9,102,3,9,9,101,2,9,9,102,4,9,9,4,9,99,3,9,102,5,9,9,4,9,99,3,9,1002,9,2,9,101,2,9,9,1002,9,2,9,4,9,99,3,9,1002,9,4,9,101,3,9,9,4,9,99,3,9,1002,9,3,9,101,5,9,9,1002,9,3,9,101,3,9,9,1002,9,5,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,99,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,99