diff --git a/day19/part1.lua b/day19/part1.lua new file mode 100755 index 0000000..fd577d0 --- /dev/null +++ b/day19/part1.lua @@ -0,0 +1,194 @@ +#!/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 + +-- printtable(scanners[2]) +-- printtable(move(rotate(scanners[2], +-- {x="x", y="y", z="z"}, +-- {x=-1, y=1, z=-1}), +-- {x=68, y=-1246, z=-43})) +-- print(similar(scanners[1], move(rotate(scanners[2], +-- {x="x", y="y", z="z"}, +-- {x=-1, y=1, z=-1}), +-- {x=68, y=-1246, z=-43}))) +-- print(compare(scanners[1], scanners[2])) +-- printtable(compare(scanners[1], scanners[2])) + +-- for _, a in pairs(scanners) do +-- for _, b in pairs(scanners) do +-- moved = compare(a, b) +-- if moved == nil then +-- io.write(string.format("%3d", 0)) +-- else +-- io.write(string.format("%3d", similar(a, moved))) +-- end +-- end +-- io.write("\n") +-- 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) } +while #todos > 0 do + print(#todos) + for _, scanner in pairs(compareWiths) do + countbeacons(scanner) + end + + 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) + else + table.insert(newtodos, todo) + end + end + todos = newtodos + compareWiths = newCompareWiths +end + +for _, scanner in pairs(compareWiths) do + countbeacons(scanner) +end + +print(counter)