Advertisement
Guest User

Untitled

a guest
Dec 15th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.74 KB | None | 0 0
  1. require("utils")
  2.  
  3. local intcode = getinput()
  4.  
  5. local function Process(intcode, inputs)
  6.     local memory = parsecommas(intcode, tonumber)
  7.     memory[0] = table.remove(memory, 1)
  8.     setmetatable(memory, {
  9.         __index = function(t, k)
  10.             rawset(t, k, 0)
  11.             return 0
  12.         end;
  13.     })
  14.     local self = {
  15.         memory = memory;
  16.         ip = 0; -- instruction pointer
  17.         inputs = inputs or {}; -- input queue
  18.         halted = false;
  19.         relativeBase = 0;
  20.     }
  21.     self.thread = coroutine.create(function()
  22.         local operations = {
  23.             [1]={3, true, function(a, b) return a + b end};
  24.             [2]={3, true, function(a, b) return a * b end};
  25.             [3]={1, true, function() if #self.inputs > 0 then return table.remove(self.inputs, 1) end return self.getinput() end};
  26.             [4]={1, false, function(x) coroutine.yield(x) end};
  27.             [5]={2, false, function(a, b) if a ~= 0 then self.ip = b end end};
  28.             [6]={2, false, function(a, b) if a == 0 then self.ip = b end end};
  29.             [7]={3, true, function(a, b) return a < b and 1 or 0 end};
  30.             [8]={3, true, function(a, b) return a == b and 1 or 0 end};
  31.             [9]={1, false, function(x) self.relativeBase = self.relativeBase + x end};
  32.             [99]={0, false, function() self.halted = true end}
  33.         }
  34.         while true do
  35.             local memory = self.memory
  36.             local opcode = memory[self.ip]%100
  37.             local operation = operations[opcode]
  38.            
  39.             local paramCount = operation[1]
  40.             local writes = operation[2]
  41.             local args = {}
  42.             for i = 1, paramCount do
  43.                 local mode = memory[self.ip]//10^(i+1)%10
  44.                 local value = mode == 1 and (self.ip + i) or memory[self.ip + i]
  45.                 if mode == 2 then value = value + self.relativeBase end
  46.                 args[i] = (writes and i == paramCount) and value or memory[value]
  47.             end
  48.            
  49.             local lastip = self.ip
  50.             local result = operation[3](table.unpack(args))
  51.             if self.halted then break end
  52.             if writes then -- writes to
  53.                 memory[args[#args]] = result
  54.             end
  55.             if lastip == self.ip then -- didn't jump
  56.                 self.ip = self.ip + paramCount + 1
  57.             end
  58.         end
  59.         return "halted"
  60.     end)
  61.     function self:resume()
  62.         return ({coroutine.resume(self.thread)})[2]
  63.     end
  64.     function self:input(value)
  65.         table.insert(self.inputs, value)
  66.     end
  67.     function self:copy()
  68.         local new = Process(intcode, {table.unpack(self.inputs)})
  69.         new.ip = self.ip
  70.         new.halted = self.halted
  71.         new.relativeBase = self.relativeBase
  72.         new.memory = {}
  73.         for k, v in pairs(self.memory) do
  74.             new.memory[k] = v
  75.         end
  76.         if self.memory[self.ip]%100 == 4 then
  77.             new.ip = new.ip + 2
  78.         end
  79.         return new
  80.     end
  81.     return self
  82. end
  83.  
  84. local visited = {}
  85. local dir = {{0,1},{0,-1},{1,0},{-1,0}}
  86. local opposite = {2,1,4,3}
  87. local paths = {}
  88. for i = 1, 4 do
  89.     paths[i] = {length = 1, x = dir[i][1], y = dir[i][2], process = Process(intcode, {i}), backwards = opposite[i]}
  90. end
  91. local longest = 0
  92. local part2started = false
  93. while paths[1] do
  94.     local new = {}
  95.     for _, path in pairs(paths) do
  96.         local x, y = path.x, path.y
  97.         local s = x..","..y
  98.         if not visited[s] then
  99.             visited[s] = true
  100.             local status = path.process:resume()
  101.             if status ~= 0 then
  102.                 longest = math.max(longest, path.length)
  103.                 for i = 1, 4 do
  104.                     if i ~= path.backwards then
  105.                         local copy = path.process:copy()
  106.                         copy:input(i)
  107.                         new[#new+1] = {length = path.length + 1, x = path.x + dir[i][1], y = path.y + dir[i][2], process = copy, backwards = opposite[i]}
  108.                     end
  109.                 end
  110.             end
  111.             if status == 2 then
  112.                 if not part2started then
  113.                     print("minumum length: "..path.length)
  114.                     part2started = true
  115.                     visited = {}
  116.                     new = {}
  117.                     for i = 1, 4 do
  118.                         local copy = path.process:copy()
  119.                         copy:input(i)
  120.                         new[i] = {length = 1, x = x+dir[i][1], y = y+dir[i][2], process = copy, backwards = opposite[i]}
  121.                     end
  122.                     break
  123.                 end
  124.             end
  125.         end
  126.     end
  127.     paths = new
  128. end
  129. print("longest: "..longest)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement