2 changed files with 194 additions and 0 deletions
			
			
		@ -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) | 
				
			|||
@ -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 | 
				
			|||
					Loading…
					
					
				
		Reference in new issue