174 lines
4.9 KiB
Lua
174 lines
4.9 KiB
Lua
|
#!/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)
|