Last active
December 2, 2022 05:42
-
-
Save MCJack123/1c2ffbfb7f67414784118b337832b9cf to your computer and use it in GitHub Desktop.
JackMacWindows's Advent of Code 2021 programs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 3-1 | |
local file = fs.open("aoc.txt", "r") | |
local count = {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } | |
repeat | |
local l = file.readLine() | |
if not l then break end | |
l:gsub("()([01])", function(pos, num) count[pos][tonumber(num)+1] = count[pos][tonumber(num)+1] + 1 end) | |
until not l | |
file.close() | |
local gamma = 0 | |
for i = 1, 12 do gamma = bit32.bor(gamma, bit32.lshift(count[i][1] > count[i][2] and 0 or 1, 12 - i)) end | |
print(textutils.serialize(count)) | |
print(gamma) | |
local epsilon = 0 | |
for i = 1, 12 do epsilon = bit32.bor(epsilon, bit32.lshift(count[i][1] < count[i][2] and 0 or 1, 12 - i)) end | |
print(epsilon) | |
print(gamma*epsilon) | |
-- 3-2 | |
local file = fs.open("aoc.txt", "r") | |
local function filter(lines, pos, hi) | |
local count = {0, 0} | |
for _, l in ipairs(lines) do count[l:byte(pos) - 47] = count[l:byte(pos) - 47] + 1 end | |
local ok = count[1] > count[2] | |
if hi then ok = not ok end | |
ok = ok and 0 or 1 | |
local ll = {} | |
for _, l in ipairs(lines) do if l:byte(pos) - 48 == ok then ll[#ll+1] = l end end | |
if #ll == 0 then error("none") | |
elseif #ll == 1 then return ll[1] | |
else return filter(ll, pos + 1, hi) end | |
end | |
local lines = {} | |
repeat | |
local l = file.readLine() | |
lines[#lines+1] = l | |
until not l | |
local o2 = filter(lines, 1, false) | |
local co2 = filter(lines, 1, true) | |
print(o2) | |
print(co2) | |
print(tonumber(o2, 2) * tonumber(co2, 2)) | |
file.close() | |
-- 4 | |
local file = fs.open("aoc.txt", "r") | |
local sel = file.readLine() | |
local selections = {} | |
for m in sel:gmatch "%d+" do selections[#selections+1] = m end | |
file.readLine() | |
local boards = {} | |
local i = 1 | |
repeat | |
boards[i] = {} | |
local ok = false | |
repeat | |
local l = file.readLine() | |
if l == nil then break end | |
local n = {l:match("(%d+) +(%d+) +(%d+) +(%d+) +(%d+)")} | |
if #n == 0 then break end | |
boards[i][#boards[i]+1] = n | |
ok = true | |
until false | |
if not ok then boards[i] = nil end | |
i=i+1 | |
until not ok | |
local winner, sel | |
local num = #boards | |
for _,s in ipairs(selections) do | |
--print(s) | |
local nw = {} | |
local cc = 0 | |
for n = 1, num do local b = boards[n] if b then | |
cc=cc+1 | |
for _, l in ipairs(b) do | |
local row = true | |
for i = 1, 5 do | |
if l[i] == s then l[i] = nil end | |
if l[i] ~= nil then row = false end | |
end | |
if n ~= winner and row then nw[n] = true break end | |
end | |
for i = 1, 5 do | |
local col = true | |
for _, l in ipairs(b) do | |
if l[i] ~= nil then col = false end | |
end | |
if n ~= winner and col then nw[n] = true break end | |
end | |
end end | |
if cc <= 1 then break end | |
print(winner, cc) | |
sleep(0.05) | |
for nw in pairs(nw) do | |
print(nw) | |
if winner then boards[winner] = nil end | |
winner = nw | |
sel = s | |
end | |
end | |
print(winner) | |
print(sel) | |
local sum = 0 | |
for _, l in ipairs(boards[winner]) do | |
for i = 1, 5 do | |
if l[i] ~= nil then sum = sum + tonumber(l[i]) end | |
end | |
end | |
print(sum * sel) | |
file.close() | |
-- 5 | |
local file = fs.open("aoc.txt", "r") | |
local vectors = {} | |
repeat | |
local l = file.readLine() | |
if l then | |
vectors[#vectors+1] = {vector.new(0, l:match("^(%d+),(%d+)")), vector.new(0, l:match("(%d+),(%d+)$"))} | |
end | |
until not l | |
local grid = {} | |
local w, h = 0, 0 | |
for _,v in ipairs(vectors) do | |
if v[1].y == v[2].y then | |
h = math.max(h, v[1].z, v[2].z) | |
grid[v[1].y] = grid[v[1].y] or {} | |
for z = v[1].z, v[2].z, -(v[1].z - v[2].z) / math.abs(v[1].z - v[2].z) do | |
grid[v[1].y][z] = (grid[v[1].y][z] or 0) + 1 | |
end | |
elseif v[1].z == v[2].z then | |
w = math.max(w, v[1].y, v[2].y) | |
for y = v[1].y, v[2].y, -(v[1].y - v[2].y) / math.abs(v[1].y - v[2].y) do | |
grid[y] = grid[y] or {} | |
grid[y][v[1].z] = (grid[y][v[1].z] or 0) + 1 | |
end | |
else | |
w = math.max(w, v[1].y, v[2].y) | |
h = math.max(h, v[1].z, v[2].z) | |
local sy, sz = -(v[1].y - v[2].y) / math.abs(v[1].y - v[2].y), -(v[1].z - v[2].z) / math.abs(v[1].z - v[2].z) | |
for o = 0, math.abs(v[2].y - v[1].y) do | |
grid[v[1].y+o*sy] = grid[v[1].y+o*sy] or {} | |
grid[v[1].y+o*sy][v[1].z+o*sz] = (grid[v[1].y+o*sy][v[1].z+o*sz] or 0) + 1 | |
end | |
end | |
end | |
local s = 0 | |
for y = 1, w do | |
for z = 1, h do | |
if grid[y] and grid[y][z] and grid[y][z] > 1 then s = s + 1 end | |
end | |
end | |
print(s) | |
file.close() | |
-- 6-1 | |
local file = fs.open("aoc.txt", "r") | |
local s = file.readLine() | |
local t = {ffi.new("char[2147483647]")} | |
local e = 0 | |
local function insert(n) | |
e = e + 1 | |
if not t[math.floor(e / 2147483647)+1] then t[math.floor(e / 2147483647)+1] = ffi.new("char[2147483647]") end | |
t[math.floor(e / 2147483647)+1][e%2147483647] = n | |
end | |
for m in s:gmatch "%d+" do insert(tonumber(m)) end | |
file.close() | |
local start = os.epoch "utc" | |
for i = 1, 256 do | |
print(i) | |
local n = e | |
for j = 1, n do | |
if t[math.floor(j / 2147483647)+1][j%2147483647] == 0 then | |
if os.epoch "utc" - start > 5000 then sleep(0) start = os.epoch "utc" end | |
insert(8) | |
t[math.floor(j / 2147483647)+1][j%2147483647] = 7 | |
end | |
t[math.floor(j / 2147483647)+1][j%2147483647] = t[math.floor(j / 2147483647)+1][j%2147483647] - 1 | |
end | |
end | |
print(#t) | |
-- 6-2 | |
local counts = {[0] = 0, 0, 0, 0, 0, 0, 0, 0, 0} | |
local file = fs.open("aoc.txt", "r") | |
local s = file.readLine() | |
for m in s:gmatch "%d+" do counts[tonumber(m)] = counts[tonumber(m)] + 1 end | |
file.close() | |
for i = 1, 256 do | |
local zeroc = counts[0] | |
for i = 1, 8 do counts[i-1] = counts[i] end | |
counts[8] = zeroc | |
counts[6] = counts[6] + zeroc | |
end | |
local sum = 0 | |
for i = 0, 8 do sum = sum + counts[i] end | |
print(sum) | |
-- 7 | |
local file = fs.open("aoc.txt", "r") | |
local s = file.readLine() | |
local cr = {} | |
for m in s:gmatch "%d+" do cr[#cr+1] = tonumber(m) end | |
file.close() | |
local cost = {} | |
for i = 0, math.max(table.unpack(cr)) do | |
cost[i] = 0 | |
for j = 1, #cr do | |
local c = math.abs(i - cr[j]) | |
cost[i] = cost[i] + c*(c+1)/2 | |
end | |
end | |
print(math.min(table.unpack(cost))) | |
-- 8-1 | |
local file = fs.open("aoc.txt", "r") | |
local lines = {} | |
local n = 0 | |
repeat | |
local l = file.readLine() | |
if l then | |
local a = {l:match("| (%w+) (%w+) (%w+) (%w+)")} | |
if #a[1] == 2 or #a[1] == 4 or #a[1] == 3 or #a[1] == 7 then print(#a[1]) n = n + 1 end | |
if #a[2] == 2 or #a[2] == 4 or #a[2] == 3 or #a[2] == 7 then print(#a[2]) n = n + 1 end | |
if #a[3] == 2 or #a[3] == 4 or #a[3] == 3 or #a[3] == 7 then print(#a[3]) n = n + 1 end | |
if #a[4] == 2 or #a[4] == 4 or #a[4] == 3 or #a[4] == 7 then print(#a[4]) n = n + 1 end | |
end | |
until not l | |
file.close() | |
print(n) | |
-- 8-2 | |
local function match(a, b, eq) | |
local m = {} | |
for c in a:gmatch "." do m[c] = false end | |
for c in b:gmatch "." do if m[c] == false then m[c] = true elseif eq then return false end end | |
for _,v in pairs(m) do if not v then return false end end | |
return true | |
end | |
local file = fs.open("aoc.txt", "r") | |
local n = 0 | |
repeat | |
local l = file.readLine() | |
if l then | |
local nums = {} | |
local b2 = {[5] = {}, [6] = {}} | |
local b = {l:match("^(%w+)" .. (" (%w+)"):rep(9))} | |
local a = {l:match("| (%w+) (%w+) (%w+) (%w+)")} | |
local nn = {} | |
for i = 1, 10 do | |
local len = #b[i] | |
if len == 2 then nums[1] = b[i] | |
elseif len == 3 then nums[7] = b[i] | |
elseif len == 4 then nums[4] = b[i] | |
elseif len == 7 then nums[8] = b[i] | |
else b2[len][#b2[len]+1] = b[i] end | |
end | |
for i = 1, 3 do | |
local s = b2[6][i] | |
if not match(nums[1], s) then nums[6] = s | |
elseif match(nums[4], s) then nums[9] = s | |
else nums[0] = s end | |
end | |
for i = 1, 3 do | |
local s = b2[5][i] | |
if match(nums[1], s) then nums[3] = s | |
elseif match(s, nums[6]) then nums[5] = s | |
else nums[2] = s end | |
end | |
for i = 1, 4 do | |
for j = 0, 9 do | |
if match(a[i], nums[j], true) then nn[i] = j break end | |
end | |
end | |
print(table.concat(nn, "", 1, 4)) | |
n = n + tonumber(table.concat(nn, "", 1, 4)) | |
end | |
until not l | |
file.close() | |
print(n) | |
-- 9-1 | |
local file = fs.open("aoc.txt", "r") | |
local map = {} | |
repeat | |
local l = file.readLine() | |
if l then | |
local ln = {} | |
for c in l:gmatch "%d" do ln[#ln+1] = tonumber(c) end | |
map[#map+1] = ln | |
end | |
until not l | |
file.close() | |
local lown = 0 | |
for y, l in ipairs(map) do | |
for x, n in ipairs(l) do | |
if (x == 1 or l[x-1] > n) and (y == 1 or map[y-1][x] > n) and (x == #l or l[x+1] > n) and (y == #map or map[y+1][x] > n) then lown = lown + n + 1 end | |
end | |
end | |
print(lown) | |
-- 9-2 | |
local file = fs.open("aoc.txt", "r") | |
local map = {} | |
repeat | |
local l = file.readLine() | |
if l then | |
local ln = {} | |
for c in l:gmatch "%d" do ln[#ln+1] = tonumber(c) end | |
map[#map+1] = ln | |
end | |
until not l | |
file.close() | |
local basins = {} | |
local basinSize = {} | |
term.setBackgroundColor(colors.black) | |
term.clear() | |
local function checkBasin(x, y, l, n, i, ok) | |
if n == 9 or (basins[y] and basins[y][x]) then return false end | |
if x > 1 and l[x-1] > n then | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
ok = checkBasin(x - 1, y, l, l[x-1], i, true) or ok | |
end | |
if y > 1 and map[y-1][x] > n then | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
ok = checkBasin(x, y - 1, map[y-1], map[y-1][x], i, true) or ok | |
end | |
if x < #l and l[x+1] > n then | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
ok = checkBasin(x + 1, y, l, l[x+1], i, true) or ok | |
end | |
if y < #map and map[y+1][x] then | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
ok = checkBasin(x, y + 1, map[y+1], map[y+1][x], i, true) or ok | |
end | |
if ok then | |
basinSize[i] = (basinSize[i] or 0) + 1 | |
term.setCursorPos(x, y) | |
if i < 256 then term.blit(tostring(n), ("%1x"):format(i % 16), ("%1x"):format(math.floor(i / 16))) end | |
end | |
return true | |
end | |
for y, l in ipairs(map) do | |
for x, n in ipairs(l) do | |
if (x == 1 or l[x-1] > n) and (y == 1 or map[y-1][x] > n) and (x == #l or l[x+1] > n) and (y == #map or map[y+1][x] > n) then | |
local i = #basinSize+1 | |
basins[y] = basins[y] or {} | |
basins[y][x] = checkBasin(x, y, l, n, i) | |
end | |
end | |
end | |
--[=[local function checkBasin(x, y, l, n, i, ok) | |
if n == 9 or (basins[y] and basins[y][x]) then return end | |
if x > 1 and math.abs(l[x-1] - n) == 1 and l[x-1] < 9 then | |
ok = true | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
checkBasin(x - 1, y, l, l[x-1], i, true) | |
end | |
if y > 1 and math.abs(map[y-1][x] - n) == 1 and map[y-1][x] < 9 then | |
ok = true | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
checkBasin(x, y - 1, map[y-1], map[y-1][x], i, true) | |
end | |
if x < #l and math.abs(l[x+1] - n) == 1 and l[x+1] < 9 then | |
ok = true | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
checkBasin(x + 1, y, l, l[x+1], i, true) | |
end | |
if y < #map and math.abs(map[y+1][x] - n) == 1 and map[y+1][x] < 9 then | |
ok = true | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
checkBasin(x, y + 1, map[y+1], map[y+1][x], i, true) | |
end | |
if ok then | |
basins[y] = basins[y] or {} | |
basins[y][x] = true | |
--basinSize[i] = (basinSize[i] or 0) + 1 | |
--term.setCursorPos(x, y) | |
--if i < 256 then term.blit(tostring(n), ("%1x"):format(i % 16), ("%1x"):format(math.floor(i / 16))) end | |
end | |
end | |
for y, l in ipairs(map) do | |
for x, n in ipairs(l) do | |
checkBasin(x, y, l, n, #basinSize + 1, false) | |
end | |
end | |
local counted = {} | |
local function sizeBasin(x, y, i) | |
if (counted[y] and counted[y][x]) or not basins[y] or not basins[y][x] then return end | |
basinSize[i] = (basinSize[i] or 0) + 1 | |
counted[y] = counted[y] or {} | |
counted[y][x] = true | |
if x > 1 then | |
sizeBasin(x - 1, y, i) | |
end | |
if y > 1 then | |
sizeBasin(x, y - 1, i) | |
end | |
if x < #map[y] then | |
sizeBasin(x + 1, y, i) | |
end | |
if y < #map then | |
sizeBasin(x, y + 1, i) | |
end | |
end | |
for y = 1, #map do | |
for x = 1, #map[y] do | |
sizeBasin(x, y, #basinSize+1) | |
end | |
end | |
for y = 1, #map do | |
for x = 1, #map[y] do write(basins[y] and basins[y][x] and map[y][x] or " ") end | |
print() | |
end]=] | |
term.setCursorPos(1, select(2, term.getSize()) - 2) | |
term.setTextColor(colors.white) | |
term.setBackgroundColor(colors.black) | |
table.sort(basinSize, function(a, b) return a > b end) | |
print(basinSize[1], basinSize[2], basinSize[3]) | |
print(basinSize[1] * basinSize[2] * basinSize[3]) | |
-- 10 | |
local file = fs.open("aoc.txt", "r") | |
local s = {} | |
local p = {["("] = ")", ["["] = "]", ["{"] = "}", ["<"] = ">"} | |
local n = {[")"] = 3, ["]"] = 57, ["}"] = 1197, [">"] = 25137} | |
local n2 = {["("] = 1, ["["] = 2, ["{"] = 3, ["<"] = 4} | |
repeat | |
local l = file.readLine() | |
local st = {} | |
if l then | |
local ok = true | |
for x, c in l:gmatch "()([%(%[%{%<%)%]%}%>])" do | |
if p[c] then st[#st+1] = c | |
elseif p[st[#st]] == c then table.remove(st) | |
else ok = false break end | |
end | |
if ok then | |
local ss = 0 | |
for i = #st, 1, -1 do | |
ss = ss * 5 + n2[st[i]] | |
end | |
table.insert(s, ss) | |
end | |
end | |
until not l | |
file.close() | |
table.sort(s) | |
print(#s, math.ceil(#s/2), s[math.ceil(#s/2)]) | |
-- 11 | |
local file = fs.open("aoc.txt", "r") | |
local field = {} | |
local flashn = 0 | |
local function step() | |
local flashes = {} | |
for y,r in ipairs(field) do | |
for x,n in ipairs(r) do | |
r[x] = r[x] + 1 | |
end | |
end | |
repeat | |
local ok = true | |
for y,r in ipairs(field) do | |
for x,n in ipairs(r) do | |
if n > 9 and not (flashes[y] and flashes[y][x]) then | |
flashes[y] = flashes[y] or {} | |
flashes[y][x] = true | |
flashn = flashn + 1 | |
ok = false | |
if x > 1 then | |
r[x-1] = r[x-1] + 1 | |
if y > 1 then field[y-1][x-1] = field[y-1][x-1] + 1 end | |
if y < #field then field[y+1][x-1] = field[y+1][x-1] + 1 end | |
end | |
if y > 1 then field[y-1][x] = field[y-1][x] + 1 end | |
if y < #field then field[y+1][x] = field[y+1][x] + 1 end | |
if x < #r then | |
r[x+1] = r[x+1] + 1 | |
if y > 1 then field[y-1][x+1] = field[y-1][x+1] + 1 end | |
if y < #field then field[y+1][x+1] = field[y+1][x+1] + 1 end | |
end | |
end | |
end | |
end | |
until ok | |
for y,r in ipairs(field) do for x,n in ipairs(r) do if n > 9 then field[y][x] = 0 end end end | |
end | |
for i = 1, 10 do field[i] = {} file.readLine():gsub("()(%d)", function(p, c) field[i][p] = tonumber(c) end) end | |
file.close() | |
for i = 1, math.huge do | |
step() | |
local nn = field[1][1] | |
for y,r in ipairs(field) do for x,n in ipairs(r) do if n ~= nn then nn = nil break end end end | |
if nn then print(i) break end | |
end | |
print(flashn) | |
-- 12 | |
local function mcopy(t, u) local r = {} for k,v in pairs(t) do r[k] = v end for k,v in pairs(u) do r[k] = v end return r end | |
local function traverse(node, visited, max) | |
-- node: {name = "name", children...} | |
if node.name == "end" then return {"end"} end | |
local opts = {} | |
for i,v in ipairs(node) do | |
if (visited[v.name] or 0) < (max == v and 2 or 1) then | |
local t = {} | |
if node.name == node.name:lower() then t[node.name] = (visited[node.name] or 0) + 1 end | |
local r = traverse(v, mcopy(visited, t), max) | |
local f = {} | |
for _,s in ipairs(r) do opts[#opts+1], f[s] = node.name .. "," .. s, true end | |
if node.name == node.name:lower() and not max then | |
local r = traverse(v, mcopy(visited, t), node) | |
for _,s in ipairs(r) do if not f[s] then opts[#opts+1] = node.name .. "," .. s end end | |
end | |
end | |
end | |
return opts | |
end | |
local map = {} | |
for line in io.lines("aoc.txt") do | |
local s, e = line:match("^(%w+)%-(%w+)$") | |
if map[s] == nil then map[s] = {name = s} end | |
if map[e] == nil then map[e] = {name = e} end | |
map[s][#map[s]+1] = map[e] | |
map[e][#map[e]+1] = map[s] | |
end | |
local t = traverse(map.start, {start = 2}) | |
for i,v in ipairs(t) do print(v) end | |
print(#t) | |
-- 13 | |
local field = {} | |
local maxX, maxY = 0, 0 | |
local step = 0 | |
for line in io.lines("aoc.txt") do | |
if step == 0 then | |
local x, y = line:match("(%d+),(%d+)") | |
if x then | |
x, y = tonumber(x), tonumber(y) | |
maxX, maxY = math.max(maxX, x), math.max(maxY, y) | |
field[y] = field[y] or {} | |
field[y][x] = true | |
else step = 1 end | |
elseif step == 1 then | |
local c = 0 | |
for _,r in pairs(field) do for _ in pairs(r) do c = c + 1 end end | |
print(c) | |
local axis, pos = line:match "([xy])=(%d+)" | |
pos = tonumber(pos) | |
for i = pos+1, axis == "x" and maxX or maxY do | |
if axis == "x" then for y = 0, maxY do | |
field[y] = field[y] or {} | |
field[y][pos-(i-pos)] = field[y][pos-(i-pos)] or field[y][i] | |
field[y][i] = nil | |
end maxX = pos else | |
field[pos-(i-pos)] = field[pos-(i-pos)] or {} | |
field[i] = field[i] or {} | |
for x = 0, maxX do field[pos-(i-pos)][x] = field[pos-(i-pos)][x] or field[i][x] end | |
field[i] = nil | |
maxY = pos | |
end | |
end | |
end | |
end | |
for y = 0, maxY do for x = 0, maxX do if field[y] and field[y][x] then write("X") else write(" ") end end print("E") end | |
-- 14 | |
local poly | |
local rules = {} | |
for line in io.lines("aoc.txt") do | |
if not poly then poly = line | |
elseif line ~= "" then | |
rules[#rules+1] = {line:match "(%w%w) %-> (%w)"} | |
end | |
end | |
local polycount = {} | |
for n = 1, #poly - 1 do polycount[poly:sub(n, n+1)] = (polycount[poly:sub(n, n+1)] or 0) + 1 end | |
for i = 1, 40 do | |
local newp = {} | |
for k,v in pairs(rules) do | |
if polycount[v[1]] then | |
local a, b = v[1]:sub(1, 1) .. v[2], v[2] .. v[1]:sub(2, 2) | |
newp[a] = (newp[a] or 0) + (polycount[v[1]] or 0) | |
newp[b] = (newp[b] or 0) + (polycount[v[1]] or 0) | |
end | |
end | |
polycount = newp | |
end | |
local count = {} | |
for k,v in pairs(polycount) do | |
count[k:sub(1, 1)] = (count[k:sub(1, 1)] or 0) + v | |
count[k:sub(2, 2)] = (count[k:sub(2, 2)] or 0) + v | |
end | |
local c2 = {} | |
for _,v in pairs(count) do c2[#c2+1] = math.ceil(v / 2) end | |
table.sort(c2) | |
for _,v in ipairs(c2) do write(v .. " ") end | |
print(c2[#c2] - c2[1]) | |
-- 16-1 | |
local file = fs.open("aoc.txt", "r") | |
local bits = "" | |
local function bin(n, b) return bit32.btest(tonumber(n, 16), b) and "1" or "0" end | |
file.readLine():gsub("%x", function(c) bits = bits .. bin(c, 8) .. bin(c, 4) .. bin(c, 2) .. bin(c, 1) end) | |
file.close() | |
local pos = 1 | |
local function r(n) | |
if #bits < n then error(debug.traceback(#bits .. "/" .. n)) end | |
local s = bits:sub(1, n) | |
bits = bits:sub(n + 1) | |
pos = pos + n | |
return tonumber(s, 2) | |
end | |
local function readPacket() | |
local t = {} | |
t.version = r(3) | |
t.type = r(3) | |
if t.type == 4 then | |
local len = 0 | |
t.value = 0 | |
repeat | |
local n = r(5) | |
len = len + 5 | |
t.value = t.value * 16 + bit32.band(n, 15) | |
until not bit32.btest(n, 0x10) | |
elseif r(1) == 1 then | |
t.isLength = false | |
local num = r(11) | |
t.children = {} | |
for i = 1, num do t.children[i] = readPacket() end | |
else | |
t.isLength = true | |
local len = r(15) | |
if len > #bits then error(debug.traceback(len)) end | |
local e = pos + len | |
t.children = {} | |
while pos < e do t.children[#t.children+1] = readPacket() end | |
end | |
return t | |
end | |
local root = readPacket() | |
require "cc.pretty".pretty_print(root) | |
local function sumVersions(p) | |
local s = p.version | |
if p.children then for _, v in ipairs(p.children) do s = s + sumVersions(v) end end | |
return s | |
end | |
local calculate calculate = { | |
[0] = function(p) | |
local s = 0 | |
for _,v in ipairs(p.children) do s = s + calculate[v.type](v) end | |
return s | |
end, | |
function(p) | |
local s = 1 | |
for _,v in ipairs(p.children) do s = s * calculate[v.type](v) end | |
return s | |
end, | |
function(p) | |
local s = math.huge | |
for _,v in ipairs(p.children) do s = math.min(s, calculate[v.type](v)) end | |
return s | |
end, | |
function(p) | |
local s = -math.huge | |
for _,v in ipairs(p.children) do s = math.max(s, calculate[v.type](v)) end | |
return s | |
end, | |
function(p) return p.value end, | |
function(p) return calculate[p.children[1].type](p.children[1]) > calculate[p.children[2].type](p.children[2]) and 1 or 0 end, | |
function(p) return calculate[p.children[1].type](p.children[1]) < calculate[p.children[2].type](p.children[2]) and 1 or 0 end, | |
function(p) return calculate[p.children[1].type](p.children[1]) == calculate[p.children[2].type](p.children[2]) and 1 or 0 end, | |
} | |
print(sumVersions(root)) | |
print(calculate[root.type](root)) | |
-- 17-1 | |
local tx1, tx2, ty1, ty2 = 236, 262, -78, -58 | |
local x, y = 0, 0 | |
local vx, vy = 7, 2 | |
local mm = -math.huge | |
local n = 0 | |
for xx = -500, 500 do | |
for yy = -500, 500 do | |
vx, vy = xx, yy | |
x, y = 0, 0 | |
local maxy = -math.huge | |
for i = 1, 1000 do | |
x = x + vx | |
if vx > 0 then vx = vx - 1 | |
elseif vx < 0 then vx = vx + 1 end | |
y = y + vy | |
maxy = math.max(maxy, y) | |
vy = vy - 1 | |
if x >= tx1 and x <= tx2 and y >= ty1 and y <= ty2 then print("found", x, y, i) mm = math.max(mm, maxy) n = n + 1 break | |
elseif (y < ty1 and vy < 0) or ((x < tx1 or x > tx2) and vx == 0) then break end | |
end | |
end | |
end | |
print(mm, n) | |
-- 18-1 | |
local function explode(s, p) | |
local e = select(2, s:sub(p):find("%b[]")) + p - 1 | |
local l, r = select(2, s:sub(1, p):reverse():find("%d+")), s:sub(e):find("%d") | |
local ret | |
if l then l = p - l + 1 ret = s:sub(1, l - 1) .. (tonumber(s:sub(l):match("%d+")) + tonumber(s:sub(p):match("%d+"))) .. s:sub(s:sub(l):find("%D") + l - 1, p - 1) | |
else ret = s:sub(1, p - 1) end | |
ret = ret .. "0" | |
if r then r = r + e - 1 ret = ret .. s:sub(e + 1, r - 1) .. (tonumber(s:sub(r):match("%d+")) + tonumber(s:sub(p):match("%d+%D+(%d+)"))) .. s:sub(s:sub(r):find("%D") + r - 1) | |
else ret = ret .. s:sub(e + 1) end | |
return ret | |
end | |
local function split(s, p) | |
local n, e = s:sub(p):match("(%d+)()") | |
return s:sub(1, p - 1) .. "[" .. math.floor(tonumber(n) / 2) .. "," .. math.ceil(tonumber(n) / 2) .. "]" .. s:sub(p + e - 1) | |
end | |
local function reduce(s) | |
--print(s) | |
repeat | |
local ok = true | |
repeat | |
for p, a, b in s:gmatch "()%[(%d+),(%d+)%]" do | |
local o, e = select(2, s:sub(1, p - 1):gsub("%[", "")), select(2, s:sub(1, p - 1):gsub("%]", "")) | |
if o - e >= 4 then | |
s = explode(s, p) | |
--print("explo", s) | |
ok = false | |
break | |
end | |
end | |
if not ok then break end | |
local p = s:find("%d%d+") | |
if p then | |
s = split(s, p) | |
--print("split", s) | |
ok = false | |
break | |
end | |
until true | |
until ok | |
return s | |
end | |
local function add(a, b) | |
return reduce("[" .. a .. "," .. b .. "]") | |
end | |
--[[ | |
local s | |
for line in io.lines("aoc.txt") do | |
if s then s = add(s, line) | |
else s = line end | |
print(s) | |
end | |
repeat local n s, n = s:gsub("%[(%d+),(%d+)%]", function(a, b) return 3*tonumber(a) + 2*tonumber(b) end) until n == 0 | |
print(s) | |
]] | |
-- 18-2 | |
local nums = {} | |
local max = -math.huge | |
for line in io.lines("aoc.txt") do nums[#nums+1] = line end | |
for _, a in ipairs(nums) do | |
for _, b in ipairs(nums) do | |
local s = add(a, b) | |
repeat local n s, n = s:gsub("%[(%d+),(%d+)%]", function(a, b) return 3*tonumber(a) + 2*tonumber(b) end) until n == 0 | |
max = math.max(max, tonumber(s)) | |
end | |
end | |
print(max) | |
-- 20-1 | |
local enh | |
local more = 1 | |
local outer = false | |
local function makenum(a, ...) | |
if a == nil then a = outer end | |
if select("#", ...) > 0 then return makenum(...) * 2 + (a and 1 or 0) | |
else return a and 1 or 0 end | |
end | |
local function enhance(grid) | |
local retval = {} | |
local miny, maxy = math.huge, -math.huge | |
for k in pairs(grid) do miny, maxy = math.min(miny, k), math.max(maxy, k) end | |
local minx, maxx = math.huge, -math.huge | |
for y = miny, maxy do for k in pairs(grid[y] or {}) do minx, maxx = math.min(minx, k), math.max(maxx, k) end end | |
for y = miny - more, maxy + more do | |
retval[y] = {} | |
local r, lr, nr = grid[y] or {}, grid[y-1] or {}, grid[y+1] or {} | |
for k in pairs(r) do minx, maxx = math.min(minx, k), math.max(maxx, k) end | |
for x = minx - more, maxx + more do | |
retval[y][x] = enh[makenum(nr[x+1], nr[x], nr[x-1], r[x+1], r[x], r[x-1], lr[x+1], lr[x], lr[x-1])] | |
end | |
end | |
if enh[0] then outer = not outer end | |
return retval | |
end | |
local grid = {} | |
for line in io.lines("aoc.txt") do | |
if not enh then | |
enh = {} | |
for i = 0, 511 do enh[i] = line:sub(i+1, i+1) == '#' end | |
elseif line ~= "" then | |
local t = {} | |
line:gsub("[%.#]", function(c) t[#t+1] = c == '#' end) | |
grid[#grid+1] = t | |
end | |
end | |
local ngrid = grid | |
for i = 1, 50 do ngrid = enhance(ngrid) end | |
local num = 0 | |
local miny, maxy = math.huge, -math.huge | |
for k in pairs(ngrid) do miny, maxy = math.min(miny, k), math.max(maxy, k) end | |
for y = miny, maxy do | |
local r = ngrid[y] or {} | |
local minx, maxx = math.huge, -math.huge | |
for k in pairs(r) do minx, maxx = math.min(minx, k), math.max(maxx, k) end | |
for x = minx, maxx do if r[x] then num = num + 1 end end | |
end | |
print(num) | |
-- 21-1 | |
local p1, p2 = 6, 8 | |
local rolls, p1s, p2s = 0, 0, 0 | |
local function roll() | |
rolls = rolls + 1 | |
return (rolls - 1) % 100 + 1 | |
end | |
while p1s < 1000 and p2s < 1000 do | |
local n = roll() + roll() + roll() | |
p1 = (p1 + n) % 10 | |
p1s = p1s + p1 + 1 | |
if p1s >= 1000 then break end | |
n = roll() + roll() + roll() | |
p2 = (p2 + n) % 10 | |
p2s = p2s + p2 + 1 | |
end | |
print(p1s, p2s, rolls) | |
print((p1s > p2s and p2s or p1s) * rolls) | |
-- 21-2 | |
local nn = {0, 0, 1, 3, 6, 7, 6, 3, 1} | |
local function doit(n1, n2, n1c, n2c, p1, p2, p1s, p2s, l) | |
if n1 > 0 then | |
p1 = (p1 + n1) % 10 | |
p1s = p1s + p1 + 1 | |
if p1s >= 21 then return n1c, 0 end | |
if n2 == 0 then return 0, 0 end | |
p2 = (p2 + n2) % 10 | |
p2s = p2s + p2 + 1 | |
if p2s >= 21 then return 0, n2c end | |
end | |
local w1, w2 = 0, 0 | |
for a = 3, 9 do | |
local cc1 = doit(a, 0, nn[a], 0, p1, p2, p1s, p2s, l + 1) | |
if cc1 == 0 then for b = 3, 9 do | |
local c1, c2 = doit(a, b, nn[a] * nn[b], nn[a] * nn[b], p1, p2, p1s, p2s, l + 1) | |
w1, w2 = w1 + c1, w2 + c2 | |
end else w1 = w1 + cc1 end | |
end | |
return w1 * n1c, w2 * n2c | |
end | |
local w1, w2 = doit(0, 0, 1, 1, 6, 8, 0, 0, 1) | |
print(("%d"):format(w1), ("%d"):format(w2)) | |
-- 22-1 | |
local field = {} | |
local function set(state, x1, x2, y1, y2, z1, z2) | |
for z = math.max(z1, -50), math.min(z2, 50) do field[z] = field[z] or {} for y = math.max(y1, -50), math.min(y2, 50) do field[z][y] = field[z][y] or {} for x = math.max(x1, -50), math.min(x2, 50) do field[z][y][x] = state end end end | |
end | |
for line in io.lines("aoc.txt") do | |
local state = line:sub(1, 2) == "on" or nil | |
set(state, line:match("x=(%-?%d+)%.%.(%-?%d+),y=(%-?%d+)%.%.(%-?%d+),z=(%-?%d+)%.%.(%-?%d+)")) | |
end | |
local n = 0 | |
for _, p in pairs(field) do for _, r in pairs(p) do for _ in pairs(r) do n = n + 1 end end end | |
print(n) | |
-- 22-2 | |
local function num(n, ...) if n then return tonumber(n), num(...) end end | |
local function c0(...) for i, v in ipairs{...} do if v <= 0 then error("index " .. i .. " is less than 1 (" .. v .. ")", 2) end end return ... end | |
local function volume(b) return c0(b[2] - b[1] + 1) * | |
c0(b[4] - b[3] + 1) * | |
c0(b[6] - b[5] + 1) end | |
local function outside(axis, box, region) | |
if box[axis] < region[axis+1] and box[axis+1] > region[axis+2] then return box[axis], region[axis+1]-1, region[axis+2]+1, box[axis+1] | |
elseif box[axis] < region[axis+1] then return box[axis], region[axis+1]-1 | |
elseif box[axis+1] > region[axis+2] then return region[axis+2]+1, box[axis+1] | |
else error("invalid outside region", 2) end | |
end | |
local function inside(axis, box, region) | |
if box[axis] <= region[axis+1] and box[axis+1] >= region[axis+2] then return region[axis+1], region[axis+2] | |
elseif box[axis] <= region[axis+1] then return region[axis+1], box[axis+1] | |
elseif box[axis+1] >= region[axis+2] then return box[axis], region[axis+2] | |
else return box[axis], box[axis+1] end | |
end | |
local inst = {} | |
for line in io.lines("aoc.txt") do table.insert(inst, 1, {line:sub(1, 2) == "on" or nil, num(line:match("x=(%-?%d+)%.%.(%-?%d+),y=(%-?%d+)%.%.(%-?%d+),z=(%-?%d+)%.%.(%-?%d+)"))}) end | |
local regions = {} | |
for i, v in ipairs(inst) do if v[1] then | |
print("region", i, #regions) | |
-- split each region into unique, non-intersecting (with previous instructions) boxes | |
local boxes = {{table.unpack(v, 2, 7)}} | |
for j = 1, i - 1 do | |
local w = inst[j] | |
local nb = {} | |
--print("region:", table.unpack(w, 2, 7)) | |
--print("boxes:", #boxes) | |
-- determine collision of each box | |
for _, b in ipairs(boxes) do | |
--print(table.unpack(b, 1, 6)) | |
-- if this box does not collide, then add the whole thing | |
if not (((b[2] >= w[2] and b[2] <= w[3]) or (b[1] <= w[3] and b[2] >= w[3])) and | |
((b[4] >= w[4] and b[4] <= w[5]) or (b[3] <= w[5] and b[4] >= w[5])) and | |
((b[6] >= w[6] and b[6] <= w[7]) or (b[5] <= w[7] and b[6] >= w[7]))) then | |
--print("no collision") | |
nb[#nb+1] = b | |
else | |
-- check which axes are completely inside the region | |
local xcontain, ycontain, zcontain = b[1] >= w[2] and b[2] <= w[3], b[3] >= w[4] and b[4] <= w[5], b[5] >= w[6] and b[6] <= w[7] | |
-- check which axes are through both sides of the region | |
local xthru, ythru, zthru = b[1] < w[2] and b[2] > w[3], b[3] < w[4] and b[4] > w[5], b[5] < w[6] and b[6] > w[7] | |
-- if this box is 100% inside the region, skip it | |
local oldn = #nb | |
if not (xcontain and ycontain and zcontain) then | |
if (xcontain and 1 or 0) + (ycontain and 1 or 0) + (zcontain and 1 or 0) == 2 then | |
-- two wholly contained axes: truncate the remaining axis | |
-- if the non-contained axis is longer than the region, create two new boxes | |
-- 12 possible permutations | |
--write("2x0 ") | |
local newbox, newbox2 = {}, nil | |
if xcontain then newbox[1], newbox[2] = b[1], b[2] | |
elseif xthru then | |
newbox2 = {} | |
newbox[1], newbox[2], newbox2[1], newbox2[2] = outside(1, b, w) | |
else newbox[1], newbox[2] = outside(1, b, w) end | |
if ycontain then newbox[3], newbox[4] = b[3], b[4] | |
elseif ythru then | |
newbox2 = {} | |
newbox[3], newbox[4], newbox2[3], newbox2[4] = outside(3, b, w) | |
else newbox[3], newbox[4] = outside(3, b, w) end | |
if zcontain then newbox[5], newbox[6] = b[5], b[6] | |
elseif zthru then | |
newbox2 = {} | |
newbox[5], newbox[6], newbox2[5], newbox2[6] = outside(5, b, w) | |
else newbox[5], newbox[6] = outside(5, b, w) end | |
nb[#nb+1] = newbox | |
if newbox2 then for n = 1, 6 do newbox2[n] = newbox2[n] or newbox[n] end nb[#nb+1] = newbox2 end | |
--if newbox2 then print(volume(newbox), volume(newbox2)) | |
--else print(volume(newbox)) end | |
elseif xcontain or ycontain or zcontain then | |
-- one wholly contained axis | |
if (xthru and 1 or 0) + (ythru and 1 or 0) + (zthru and 1 or 0) == 2 then | |
-- two axes through: split into four boxes | |
-- three possible permutations | |
--print("1x2") | |
local b1, b2, b3, b4 = {}, {}, {}, {} | |
if xcontain then | |
b1[1], b1[2], b2[1], b2[2], b3[1], b3[2], b4[1], b4[2] = b[1], b[2], b[1], b[2], b[1], b[2], b[1], b[2] | |
b1[3], b1[4], b2[3], b2[4] = b[3], b[4], b[3], b[4] | |
b1[5], b1[6], b2[5], b2[6] = outside(5, b, w) | |
b3[3], b3[4], b4[3], b4[4] = outside(3, b, w) | |
b3[5], b3[6] = inside(5, b, w) | |
b4[5], b4[6] = inside(5, b, w) | |
elseif ycontain then | |
b1[3], b1[4], b2[3], b2[4], b3[3], b3[4], b4[3], b4[4] = b[3], b[4], b[3], b[4], b[3], b[4], b[3], b[4] | |
b1[1], b1[2], b2[1], b2[2] = b[1], b[2], b[1], b[2] | |
b1[5], b1[6], b2[5], b2[6] = outside(5, b, w) | |
b3[1], b3[2], b4[1], b4[2] = outside(1, b, w) | |
b3[5], b3[6] = inside(5, b, w) | |
b4[5], b4[6] = inside(5, b, w) | |
else | |
b1[5], b1[6], b2[5], b2[6], b3[5], b3[6], b4[5], b4[6] = b[5], b[6], b[5], b[6], b[5], b[6], b[5], b[6] | |
b1[3], b1[4], b2[3], b2[4] = b[3], b[4], b[3], b[4] | |
b1[1], b1[2], b2[1], b2[2] = outside(1, b, w) | |
b3[3], b3[4], b4[3], b4[4] = outside(3, b, w) | |
b3[1], b3[2] = inside(1, b, w) | |
b4[1], b4[2] = inside(1, b, w) | |
end | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
nb[#nb+1] = b4 | |
elseif xthru or ythru or zthru then | |
-- one axis through: split into three boxes | |
-- 12 possible permutations | |
--print("1x1") | |
local taxis = zthru and 5 or (ythru and 3 or 1) | |
local caxis = zcontain and 5 or (ycontain and 3 or 1) | |
local naxis = (not zthru and not zcontain) and 5 or ((not ythru and not ycontain) and 3 or 1) | |
local b1, b2, b3 = {}, {}, {} | |
b1[taxis], b1[taxis+1], b3[taxis], b3[taxis+1] = outside(taxis, b, w) | |
b2[taxis], b2[taxis+1] = inside(taxis, b, w) | |
b1[caxis], b1[caxis+1], b2[caxis], b2[caxis+1], b3[caxis], b3[caxis+1] = | |
b[caxis], b[caxis+1], b[caxis], b[caxis+1], b[caxis], b[caxis+1] | |
b1[naxis], b1[naxis+1], b3[naxis], b3[naxis+1], b2[naxis], b2[naxis+1] = | |
b[naxis], b[naxis+1], b[naxis], b[naxis+1], outside(naxis, b, w) | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
else | |
-- no axes through: split into two boxes | |
-- 12 possible permutations | |
--write("1x0 ") | |
local b1, b2 = {}, {} | |
b1[1], b1[2] = b[1], b[2] | |
b2[5], b2[6] = inside(5, b, w) | |
if xcontain then | |
b2[1], b2[2] = b[1], b[2] | |
b2[3], b2[4] = outside(3, b, w) | |
else | |
b2[1], b2[2] = outside(1, b, w) | |
b2[3], b2[4] = inside(3, b, w) | |
end | |
if zcontain then | |
b1[3], b1[4] = outside(3, b, w) | |
b1[5], b1[6] = b[5], b[6] | |
else | |
b1[3], b1[4] = b[3], b[4] | |
b1[5], b1[6] = outside(5, b, w) | |
end | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
--write(volume(b1) .. " ") | |
--print(volume(b2)) | |
end | |
else | |
if xthru and ythru and zthru then | |
-- three axes through: split into six boxes | |
-- one possible permutation | |
--print("0x3") | |
local b1, b2, b3, b4, b5, b6 = {}, {}, {}, {}, {}, {} | |
b1[1], b1[2], b1[3], b1[4], b2[1], b2[2], b2[3], b2[4] = b[1], b[2], b[3], b[4], b[1], b[2], b[3], b[4] | |
b1[5], b1[6], b2[5], b2[6] = outside(5, b, w) | |
b3[1], b3[2], b4[1], b4[2] = outside(1, b, w) | |
b3[3], b3[4], b4[3], b4[4] = b[3], b[4], b[3], b[4] | |
b3[5], b3[6] = inside(5, b, w) | |
b4[5], b4[6] = inside(5, b, w) | |
b5[1], b5[2] = inside(1, b, w) | |
b6[1], b6[2] = inside(1, b, w) | |
b5[3], b5[4], b6[3], b6[4] = outside(3, b, w) | |
b5[5], b5[6] = inside(5, b, w) | |
b6[5], b6[6] = inside(5, b, w) | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
nb[#nb+1] = b4 | |
nb[#nb+1] = b5 | |
nb[#nb+1] = b6 | |
elseif (xthru and 1 or 0) + (ythru and 1 or 0) + (zthru and 1 or 0) == 2 then | |
-- two axes through: split into five boxes | |
-- six possible permutations | |
--write("0x2 ") | |
local taxis1 = xthru and 1 or (ythru and 3 or 5) | |
local naxis = (not zthru and not zcontain) and 5 or ((not ythru and not ycontain) and 3 or 1) | |
local t = {true, nil, true, nil, true} | |
t[taxis1] = nil | |
t[naxis] = nil | |
local taxis2 = next(t) | |
assert(taxis1 ~= taxis2) | |
assert(taxis2 ~= naxis) | |
assert(naxis ~= taxis1) | |
local b1, b2, b3, b4, b5 = {}, {}, {}, {}, {} | |
b1[taxis1], b1[taxis1+1], b2[taxis1], b2[taxis1+1] = b[taxis1], b[taxis1+1], b[taxis1], b[taxis1+1] | |
b1[taxis2], b1[taxis2+1], b2[taxis2], b2[taxis2+1] = outside(taxis2, b, w) | |
b1[naxis], b1[naxis+1], b2[naxis], b2[naxis+1] = b[naxis], b[naxis+1], b[naxis], b[naxis+1] | |
b3[taxis1], b3[taxis1+1], b4[taxis1], b4[taxis1+1] = outside(taxis1, b, w) | |
b3[taxis2], b3[taxis2+1] = inside(taxis2, b, w) b4[taxis2], b4[taxis2+1] = inside(taxis2, b, w) | |
b3[naxis], b3[naxis+1], b4[naxis], b4[naxis+1] = b[naxis], b[naxis+1], b[naxis], b[naxis+1] | |
b5[taxis1], b5[taxis1+1] = inside(taxis1, b, w) | |
b5[taxis2], b5[taxis2+1] = inside(taxis2, b, w) | |
b5[naxis], b5[naxis+1] = outside(naxis, b, w) | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
nb[#nb+1] = b4 | |
nb[#nb+1] = b5 | |
--write(volume(b1) .. " ") | |
--write(volume(b2) .. " ") | |
--write(volume(b3) .. " ") | |
--write(volume(b4) .. " ") | |
--print(volume(b5)) | |
elseif xthru or ythru or zthru then | |
-- one axis through: split into four boxes | |
-- 12 possible permutations | |
--print("0x1") | |
local b1, b2, b3, b4 = {b[1], b[2], b[3], b[4], outside(5, b, w)}, {}, {}, {} | |
b2[1], b2[2] = outside(1, b, w) | |
b2[3], b2[4] = b[3], b[4] | |
b2[5], b2[6] = inside(5, b, w) | |
b3[1], b3[2] = inside(1, b, w) | |
b3[3], b3[4] = outside(3, b, w) | |
b3[5], b3[6] = inside(5, b, w) | |
if xthru then | |
b4[1], b4[2] = select(3, outside(1, b, w)) | |
b4[3], b4[4] = b[3], b[4] | |
b4[5], b4[6] = inside(5, b, w) | |
elseif ythru then | |
b4[1], b4[2] = inside(1, b, w) | |
b4[3], b4[4] = select(3, outside(3, b, w)) | |
b4[5], b4[6] = inside(5, b, w) | |
else | |
b4 = {b[1], b[2], b[3], b[4], select(3, outside(5, b, w))} | |
end | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
nb[#nb+1] = b4 | |
else | |
-- no axes through: split into three boxes | |
-- eight possible permutations | |
--write("0x0 ") | |
local b1, b2, b3 = {b[1], b[2], b[3], b[4], outside(5, b, w)}, {}, {} | |
b2[1], b2[2] = outside(1, b, w) | |
b2[3], b2[4] = b[3], b[4] | |
b2[5], b2[6] = inside(5, b, w) | |
b3[1], b3[2] = inside(1, b, w) | |
b3[3], b3[4] = outside(3, b, w) | |
b3[5], b3[6] = inside(5, b, w) | |
nb[#nb+1] = b1 | |
nb[#nb+1] = b2 | |
nb[#nb+1] = b3 | |
--print(volume(b1), volume(b2), volume(b3)) | |
end | |
end | |
end | |
local vv = 0 | |
for n = oldn + 1, #nb do for i = 1, 6 do assert(nb[n][i], n .. "/" .. i) end vv = vv + volume(nb[n]) end | |
assert(vv < volume(b)) | |
end | |
end | |
boxes = nb | |
if #boxes == 0 then break end | |
end | |
-- add the resulting unique boxes to the list with the state | |
for _, b in ipairs(boxes) do regions[#regions+1] = b end | |
end end | |
local vol = 0 | |
for i, v in ipairs(regions) do vol = vol + volume(v) end | |
print("volume", ("%d"):format(vol)) | |
-- 24-1 | |
local modnum = "13579246899999" | |
local p = 1 | |
local function input() | |
p = p + 1 | |
return modnum:byte(p-1) - ("0"):byte() | |
end | |
local reg = {w = 0, x = 0, y = 0, z = 0} | |
local inst = {} | |
function inst.inp(v) | |
reg[v] = input() | |
end | |
function inst.out(v) | |
print(reg[v]) | |
end | |
function inst.add(a, b) | |
local va, vb = reg[a], tonumber(b) or reg[b] | |
reg[a] = va + vb | |
end | |
function inst.mul(a, b) | |
local va, vb = reg[a], tonumber(b) or reg[b] | |
reg[a] = va * vb | |
end | |
function inst.div(a, b) | |
local va, vb = reg[a], tonumber(b) or reg[b] | |
reg[a] = math.floor(va / vb) | |
end | |
function inst.mod(a, b) | |
local va, vb = reg[a], tonumber(b) or reg[b] | |
reg[a] = math.floor(va % vb) | |
end | |
function inst.eql(a, b) | |
local va, vb = reg[a], tonumber(b) or reg[b] | |
reg[a] = va == vb and 1 or 0 | |
end | |
local function exec(prog) | |
reg = {w = 0, x = 0, y = 0, z = 0} | |
p = 1 | |
for _,tok in ipairs(prog) do inst[tok[1]](table.unpack(tok, 2)) end | |
return reg.z == 0 | |
end | |
local program = {} | |
for line in io.lines("aoc.txt") do | |
local tok = {} | |
for t in line:gmatch "%S+" do tok[#tok+1] = t end | |
program[#program+1] = tok | |
end | |
while true do | |
modnum = read() | |
if #modnum < 14 then break end | |
print(exec(program)) | |
end | |
--[[for i = 99999999999999, 11111111111111, -1 do | |
if i % 100000 == 0 then print(i) end | |
if not tostring(i):find("0", 1, true) then | |
modnum = tostring(i) | |
if exec(program) then print(i) return end | |
end | |
end]] | |
--[[local grid = {} | |
for i = 1, 14 do | |
grid[i] = {} | |
modnum = ("9"):rep(14) | |
for j = 1, 9 do | |
modnum = modnum:sub(1, i-1) .. j .. modnum:sub(i+1) | |
grid[i][j] = exec(program) and "#" or "." | |
end | |
end | |
for y,r in ipairs(grid) do for x,c in ipairs(r) do write(c) end print() end]] | |
-- 25-1 | |
local grid = {} | |
local w = 0 | |
for line in io.lines("aoc.txt") do | |
local r = {} | |
local i = 1 | |
for c in line:gmatch "." do | |
if c == ">" then r[i] = 1 | |
elseif c == "v" then r[i] = 2 end | |
i=i+1 | |
end | |
grid[#grid+1] = r | |
w = i - 1 | |
end | |
for step = 1, math.huge do | |
local exit = true | |
for i = 1, 2 do | |
local move = {} | |
for y, r in ipairs(grid) do for x, v in pairs(r) do if i == v then | |
local ok | |
if i == 1 then ok = grid[y][x%w+1] == nil | |
else ok = grid[y%#grid+1][x] == nil end | |
if ok then move[#move+1] = {x, y} end | |
end end end | |
for _, c in ipairs(move) do | |
exit = false | |
if i == 1 then grid[c[2]][c[1]%w+1] = i | |
else grid[c[2]%#grid+1][c[1]] = i end | |
grid[c[2]][c[1]] = nil | |
end | |
end | |
if exit then print(step) break end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <fstream> | |
#include <thread> | |
#include <string> | |
#include <mutex> | |
size_t sz = 2147483648; | |
size_t end = 0; | |
#define threadCount 16 | |
unsigned char * buf; | |
std::mutex buflock; | |
void insert(int num) { | |
std::lock_guard lock(buflock); | |
if (end + 1 > sz) { | |
buf = (unsigned char*)realloc(buf, sz *= 2); | |
} | |
buf[++end] = num; | |
} | |
void looptask(int tnum) { | |
for (int i = tnum; i < end; i += threadCount) { | |
for (int j = 0; j < 256; j++) { | |
if (buf[i] == 0) { | |
insert(8); | |
buf[i] = 7; | |
} | |
buf[i]--; | |
} | |
if (tnum == 0 && i % 65536 == 0) std::cout << i << " " << end << "\n"; | |
} | |
} | |
int main() { | |
std::ifstream in("aoc.txt"); | |
std::string s; | |
std::getline(in, s); | |
in.close(); | |
buf = (unsigned char*)malloc(sz); | |
for (int i = 0; i < s.size(); i += 2) insert(s[i] - '0'); | |
std::thread threads[threadCount]; | |
for (int j = 0; j < threadCount; j++) threads[j] = std::thread(looptask, j); | |
for (int j = 0; j < threadCount; j++) threads[j].join(); | |
std::cout << end << "\n"; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment