day 8 part 2
This commit is contained in:
parent
0416db0542
commit
3f81bb1d8b
3 changed files with 232 additions and 0 deletions
110
day08/part2.lua
Executable file
110
day08/part2.lua
Executable file
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env luajit
|
||||
require("utils")
|
||||
require("set")
|
||||
|
||||
local entries = {}
|
||||
for line in io.lines(arg[3]) do
|
||||
local entry = split(line, " ")
|
||||
table.remove(entry, 11)
|
||||
table.insert(entries, entry)
|
||||
end
|
||||
|
||||
function uniques(segment)
|
||||
if #segment == 2 then return "cf" end
|
||||
if #segment == 3 then return "acf" end
|
||||
if #segment == 4 then return "bcdf" end
|
||||
end
|
||||
|
||||
function reduceoptions(options, segment)
|
||||
local included = uniques(segment)
|
||||
if included then
|
||||
for part in chars("abcdgef") do
|
||||
if string.find(segment, part) then
|
||||
options[part]:keeponly(chars(included))
|
||||
else
|
||||
options[part]:removeall(chars(included))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function printoptions(options)
|
||||
for from, s in pairs(options) do
|
||||
io.write(from..":")
|
||||
for to in s:iter() do
|
||||
io.write(to)
|
||||
end
|
||||
io.write(" ")
|
||||
end
|
||||
io.write("\n")
|
||||
end
|
||||
|
||||
function asdigit(segment, sel)
|
||||
local lit = set()
|
||||
for c in chars(segment) do
|
||||
lit:add(sel[c])
|
||||
end
|
||||
|
||||
if lit:equal(set(chars("acbefg"))) then return 0 end
|
||||
if lit:equal(set(chars("cf"))) then return 1 end
|
||||
if lit:equal(set(chars("acdeg"))) then return 2 end
|
||||
if lit:equal(set(chars("acdfg"))) then return 3 end
|
||||
if lit:equal(set(chars("bcdf"))) then return 4 end
|
||||
if lit:equal(set(chars("abdfg"))) then return 5 end
|
||||
if lit:equal(set(chars("abdefg"))) then return 6 end
|
||||
if lit:equal(set(chars("acf"))) then return 7 end
|
||||
if lit:equal(set(chars("abcdefg"))) then return 8 end
|
||||
if lit:equal(set(chars("abcdfg"))) then return 9 end
|
||||
end
|
||||
|
||||
function backtrack(options, displays, display, segment, acc, sel, rev)
|
||||
if display > #displays then
|
||||
return set({acc})
|
||||
elseif segment <= #displays[display] then
|
||||
local pickfor = char(displays[display], segment)
|
||||
local picked = sel[pickfor]
|
||||
if picked then
|
||||
return backtrack(options, displays, display, segment+1, acc, sel, rev)
|
||||
else
|
||||
local accs = set()
|
||||
for picked in options[char(displays[display], segment)]:iter() do
|
||||
sel[pickfor] = picked
|
||||
if not rev:has(picked) then
|
||||
rev:add(picked)
|
||||
accs:addall(backtrack(options, displays, display, segment+1, acc, sel, rev):iter())
|
||||
rev:remove(picked)
|
||||
end
|
||||
end
|
||||
sel[pickfor] = nil
|
||||
return accs
|
||||
end
|
||||
else
|
||||
local digit = asdigit(displays[display], sel)
|
||||
if digit then
|
||||
return backtrack(options, displays, display + 1, 1, (acc * 10 + digit) % 10000, sel, rev)
|
||||
else
|
||||
return set()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function outputvalue(entry)
|
||||
local options = { a = set(chars('abcdefg')),
|
||||
b = set(chars('abcdefg')),
|
||||
c = set(chars('abcdefg')),
|
||||
d = set(chars('abcdefg')),
|
||||
e = set(chars('abcdefg')),
|
||||
f = set(chars('abcdefg')),
|
||||
g = set(chars('abcdefg')) }
|
||||
|
||||
for k, v in pairs(entry) do reduceoptions(options, v) end
|
||||
local solutions = backtrack(options, entry, 1, 1, 0, {}, set())
|
||||
if solutions.size == 1 then
|
||||
return solutions:iter()()
|
||||
else
|
||||
error("meh")
|
||||
end
|
||||
end
|
||||
|
||||
foreach(entries, outputvalue)
|
||||
print(sum(entries))
|
Loading…
Add table
Add a link
Reference in a new issue