Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local meta = {}
- local function wrap(v) return setmetatable(v, meta) end
- meta.__sub = function(a, b) return wrap({x = a.x - b.x, y = a.y - b.y, z = a.z - b.z}) end
- meta.__add = function(a, b) return wrap({x = a.x + b.x, y = a.y + b.y, z = a.z + b.z}) end
- meta.__eq = function(a, b) return a.x == b.x and a.y == b.y and a.z == b.z end
- local orientations = {}
- local directions = {
- wrap({x=1, y=0, z=0}), wrap({x=0, y=1, z=0}), wrap({x=0, y=0, z=1}),
- wrap({x=-1, y=0, z=0}), wrap({x=0, y=-1, z=0}), wrap({x=0, y=0, z=-1})
- }
- local function cross(a, b)
- return wrap({x = a.y*b.z - a.z*b.y, y = -a.x*b.z + a.z*b.x, z = a.x*b.y - a.y*b.x})
- end
- local function dot(a, b)
- return a.x*b.x + a.y*b.y + a.z*b.z
- end
- for i = 1, 6 do
- for j = 1, 6 do
- local a, b = directions[i], directions[j]
- local c = cross(a, b)
- if c ~= wrap({x=0, y=0, z=0}) then
- orientations[#orientations+1] = {a, b, c}
- end
- end
- end
- local function orient(v, i)
- local o = orientations[i]
- return wrap({x = dot(v, o[1]), y = dot(v, o[2]), z = dot(v, o[3])})
- end
- local scanners = {}
- local results
- local input = getinput()
- for v in input:gmatch("[^\n]+") do
- local n = v:match("scanner (%d+)")
- if n then
- results = {}
- scanners[tonumber(n)] = results
- else
- local x, y, z = v:match("(.+),(.+),(.+)")
- results[#results+1] = wrap({x = tonumber(x), y = tonumber(y), z = tonumber(z)})
- end
- end
- local function hash(v)
- return v.x..","..v.y..","..v.z
- end
- local set = {}
- local overlaps = {}
- local connections = {}
- for i = 0, #scanners do
- connections[i] = {}
- overlaps[i] = {}
- for o = 1, 24 do
- overlaps[i][o] = {}
- for a = 1, #scanners[i] do
- overlaps[i][o][a] = {}
- for j = 0, #scanners do
- overlaps[i][o][a][j] = {}
- for b = 1, #scanners[j] do
- overlaps[i][o][a][j][b] = 0
- end
- end
- end
- end
- end
- for i = 0, #scanners do
- local scanner = scanners[i]
- for o = 1, 24 do
- for a = 12, #scanner do
- for A = 1, #scanner do
- local h = hash(orient(scanner[A] - scanner[a], o))
- set[h] = set[h] or {}
- if o == 1 then
- set[h][#set[h]+1] = {i, a}
- end
- for _, m in pairs(set[h]) do
- local j, b = m[1], m[2]
- if j ~= i then
- overlaps[i][o][a][j][b] = overlaps[i][o][a][j][b] + 1
- if overlaps[i][o][a][j][b] == 12 then
- if not connections[i][j] then
- connections[i][j] = {a, b}
- connections[j][i] = {b, a}
- print("connected", i, j)
- end
- end
- end
- end
- end
- end
- end
- end
- local points = {}
- local numpoints = #scanners[0]
- for i = 1, #scanners[0] do
- points[hash(scanners[0][i])] = true
- end
- local positions = {[0] = wrap({x=0, y=0, z=0})}
- local queue = {0}
- while queue[1] do
- local i = table.remove(queue, 1)
- for j, link in pairs(connections[i]) do
- if not positions[j] then
- print("scanners", i, j)
- local scanner0, scanner1 = scanners[i], scanners[j]
- local a, b = link[1], link[2]
- local set = {}
- for A = 1, #scanner0 do
- set[hash(scanner0[A])] = true
- end
- for o = 1, 24 do
- local oriented = {}
- for B = 1, #scanner1 do
- oriented[B] = orient(scanner1[B], o)
- end
- local matches = 0
- for B = 1, #scanner1 do
- if set[hash(oriented[B] - oriented[b] + scanner0[a])] then
- matches = matches + 1
- if matches == 12 then break end
- end
- end
- if matches == 12 then
- positions[j] = positions[i] + oriented[b] - scanner0[a]
- for B = 1, #scanner1 do
- scanner1[B] = oriented[B]
- local h = hash(scanner1[B] - positions[j])
- if not points[h] then
- points[h] = true
- numpoints = numpoints + 1
- end
- end
- queue[#queue+1] = j
- break
- end
- end
- end
- end
- end
- print(numpoints)
- local highest = 0
- for i = 0, #scanners do
- for j = i+1, #scanners do
- local d = positions[i] - positions[j]
- highest = math.max(highest, math.abs(d.x) + math.abs(d.y) + math.abs(d.z))
- end
- end
- print(highest)
Add Comment
Please, Sign In to add comment