#!/usr/bin/env luajit require("utils") require("pqueue") local scanners = {} local scanner = {} for line in io.lines(arg[3]) do if #line == 0 then table.insert(scanners, scanner) scanner = {} elseif char(line, 2) == "-" then else local x, y, z = unpack(split(line, ",")) local beacon = { x = tonumber(x) , y = tonumber(y) , z = tonumber(z) } -- , q = pqueue() } table.insert(scanner, beacon) end end table.insert(scanners, scanner) for _, scanner in pairs(scanners) do for i = 1, #scanner do for j = i + 1, #scanner do local d = (scanner[i].x - scanner[j].x) ^ 2 + (scanner[i].y - scanner[j].y) ^ 2 + (scanner[i].z - scanner[j].z) ^ 2 -- scanner[i].q:add(d) -- if #scanner[i].q.items > 4 then scanner[i].q:pop() end -- scanner[j].q:add(d); scanner[j].q:pop() -- if #scanner[j].q.items > 4 then scanner[j].q:pop() end end end end local function minp(a, b) return { x = a.x - b.x, y = a.y - b.y, z = a.z - b.z } end local function addp(a, b) return { x = a.x + b.x, y = a.y + b.y, z = a.z + b.z } end local rotations = { function(p) return { x = p.x, y = p.y, z = p.z } end , function(p) return { x = p.x, y = p.z, z = -p.y } end , function(p) return { x = p.x, y = -p.y, z = -p.z } end , function(p) return { x = p.x, y = -p.z, z = p.y } end , function(p) return { x = p.y, y = -p.x, z = p.z } end , function(p) return { x = p.y, y = p.z, z = p.x } end , function(p) return { x = p.y, y = p.x, z = -p.z } end , function(p) return { x = p.y, y = -p.z, z = -p.x } end , function(p) return { x = -p.x, y = -p.y, z = p.z } end , function(p) return { x = -p.x, y = -p.z, z = -p.y } end , function(p) return { x = -p.x, y = p.y, z = -p.z } end , function(p) return { x = -p.x, y = p.z, z = p.y } end , function(p) return { x = -p.y, y = p.x, z = p.z } end , function(p) return { x = -p.y, y = -p.z, z = p.x } end , function(p) return { x = -p.y, y = -p.x, z = -p.z } end , function(p) return { x = -p.y, y = p.z, z = -p.x } end , function(p) return { x = p.z, y = p.y, z = -p.x } end , function(p) return { x = p.z, y = p.x, z = p.y } end , function(p) return { x = p.z, y = -p.y, z = p.x } end , function(p) return { x = p.z, y = -p.x, z = -p.y } end , function(p) return { x = -p.z, y = -p.y, z = -p.x } end , function(p) return { x = -p.z, y = -p.x, z = p.y } end , function(p) return { x = -p.z, y = p.y, z = p.x } end , function(p) return { x = -p.z, y = p.x, z = -p.y } end } local function eqp(a, b) return a.x == b.x and a.y == b.y and a.z == b.z end local function rotate(a, r) local b = {} for _, p in pairs(a) do table.insert(b, r(p)) end return b end local function move(a, d) local b = {} for _, p in pairs(a) do table.insert(b, { x = p.x + d.x , y = p.y + d.y , z = p.z + d.z }) end return b end local function similar(a, b) local counter = 0 for i, pa in pairs(a) do for j, pb in pairs(b) do if eqp(pa, pb) then counter = counter + 1 break end end if counter >= 12 then return counter end end return 0 end function compare(a, b) for _, r in pairs(rotations) do local br = rotate(b, r) for _, pa1 in pairs(a) do for _, pb1 in pairs(br) do local d = minp(pa1, pb1) local b_ = move(br, d) if similar(a, b_) >= 12 then return b_, d end end end end return nil end local beacons = {} local counter = 0 local function countbeacons(scanner) for _, b in pairs(scanner) do local xs = beacons[b.x] or {} local ys = xs[b.y] or {} if ys[b.z] == nil then ys[b.z] = true counter = counter + 1 end xs[b.y] = ys beacons[b.x] = xs end end local compareWiths = { scanners[1] } local todos = { unpack(scanners, 2) } local locations = { { x=0, y=0, z=0 } } while #todos > 0 do print(#todos) local newCompareWiths = {} local newtodos = {} for _, todo in pairs(todos) do local found, d = nil for _, compareWith in pairs(compareWiths) do found, d = compare(compareWith, todo) if found then break end end if found then table.insert(newCompareWiths, found) table.insert(locations, d) else table.insert(newtodos, todo) end end todos = newtodos compareWiths = newCompareWiths end local max = 0 for i = 1, #locations do for j = i + 1, #locations do local d = math.abs(locations[i].x - locations[j].x) + math.abs(locations[i].y - locations[j].y) + math.abs(locations[i].z - locations[j].z) if d > max then max = d end end end print(max)