1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
require "ext"
local blueprints = {}
for line in io.lines() do
local bpn = line:match("Blueprint (%d+):")
bpn = tonumber(bpn)
blueprints[bpn] = {}
for robot, cost in line:gmatch("Each (%w+) robot costs (%d+) ore.") do --ore and clay
blueprints[bpn][robot] = {ore = tonumber(cost)}
end
for robot, c1, r1, c2, r2 in line:gmatch("Each (%w+) robot costs (%d+) (%w+) and (%w+) (%w+).") do
--obsidian and geode
blueprints[bpn][robot] = {[r1] = tonumber(c1),[r2]=tonumber(c2)}
end
end
print("Blueprints:")
print(blueprints)
local time = 24
local function perm_yields(n)
local memgen = {} -- memoize generation
-- permutate all the ways to yield n geodes
local function permgen(left,tbl)
--print("Perm",left)
if left < 0 then return end
if left == 0 then
local ty = table.concat(tbl)
if memgen[ty] == nil then
coroutine.yield(tbl)
memgen[ty] = true
end
end
for i = time - 1,time-left - 1,-1 do
local minesfor = time - i
if tbl[i] == nil and (minesfor <= left) then
tbl[i] = "geode"
permgen(left - minesfor,tbl)
tbl[i] = nil
end
end
end
return coroutine.wrap(function() permgen(n,{}) end)
end
local dependencies = {"clay","obsidian"}
local function rperm(a,n,perm)
local function rperm_helper(a,n,rst,restrict)
if n == 0 then
coroutine.yield(rst)
else
for _,v in pairs(a) do
local lc = #rst
rst[lc + 1] = v
rperm_helper(a,n-1,rst)
rst[lc + 1] = nil
end
end
end
return coroutine.wrap(function() rperm_helper(a,n,{}) end)
end
local state = {
minute = 0,
resources = {ore = 0, clay = 0, obsidian = 0, geode = 0},
robots = {ore = 1, clay = 0, obsidian = 0, geode = 0}
}
local function copy_state(tbl)
local newtbl = {}
for k,v in pairs(tbl) do
newtbl[k] = v
end
for _,n in pairs({"resources","robots"}) do
newtbl[n] = {}
for k,v in pairs(tbl[n]) do
newtbl[n][k] = v
end
end
return newtbl
end
local function can_build(state,blueprint,name)
---print("state",state,"blueprint",blueprint,"name",name)
for res, amt in pairs(blueprint[name]) do
if state.resources[res] < amt then
return false
end
end
return true
end
local function simulate(blueprint, state, build_order, geode_times)
while state.minute <= time do
if geode_times[state.minute] then
if not can_build(state,blueprint,"geode") then
print("Failed to build geode at",state.minute)
return false
end
elseif #build_order > 0 and can_build(state,blueprint,build_order[1]) then
local rname = build_order[1]
for res,amt in pairs(blueprint[rname]) do
state.resources[res] = state.resources[res] - amt
end
state.robots[rname] = state.robots[rname] + 1
table.remove(build_order,1)
end
for res,count in pairs(state.robots) do
state.resources[res] = state.resources[res] + count
end
state.minute = state.minute + 1
end
return true
end
local function feasable(blueprint, geode_times)
for i = 1,12 do
print("Trying with",i,"other robots")
for perm in rperm({"ore","clay","obsidian"},i) do
local state = copy_state(state)
if simulate(blueprint, state, perm, geode_times) then
print("Successful simulation")
return true
end
end
end
end
for combo in perm_yields(56) do
print("combo:",combo)
end
|