day 19 cleanup

main
magical 2022-12-19 11:42:47 -08:00
parent ee05144644
commit 634e0e7eaa
1 changed files with 36 additions and 81 deletions

View File

@ -1,6 +1,6 @@
import math import math
import re import re
sample = { sample = {
1:{ 1:{
'ore': [4, 0, 0, 0], 'ore': [4, 0, 0, 0],
@ -13,9 +13,10 @@ sample = {
'clay': [3, 0, 0, 0], 'clay': [3, 0, 0, 0],
'obsidian': [3, 8, 0, 0], 'obsidian': [3, 8, 0, 0],
'geode': [3, 0, 12, 0], 'geode': [3, 0, 12, 0],
}} }
}
robot_number = {'ore': 0, 'clay': 1, 'obsidian': 2, 'geode': 3, 'nothing': 99} robot_number = {'ore': 0, 'clay': 1, 'obsidian': 2, 'geode': 3}
def parse(line): def parse(line):
line = re.sub(r'[^\d]+', ' ', line) line = re.sub(r'[^\d]+', ' ', line)
@ -28,66 +29,38 @@ def parse(line):
} }
def simulate(blueprint, minutes=24): def simulate(blueprint, minutes=24):
B = blueprint rmax = [max(x[i] for x in blueprint.values()) for i in range(3)] + [9999]
resources = [0]*4
robots = [1,0,0,0]
rmax = [max(x[i] for x in B.values()) for i in range(3)] + [99] limit = None
if minutes >= 32:
limit = 100000
items = list(blueprint.items())
items.reverse()
worth = {} print(items)
worth['ore'] = 1
worth['clay'] = worth['ore']*B['clay'][0]
worth['obsidian'] = worth['ore']*B['obsidian'][0] + worth['clay']*B['obsidian'][1]
worth['geode'] = worth['ore']*B['geode'][0] + worth['obsidian']*B['geode'][2]
print(worth)
B_items = list(B.items())
B_items.reverse()
#B_items.append(('nothing', [0,0,0,0]))
print(B_items)
buckets = [[] for _ in range(minutes+1)] buckets = [[] for _ in range(minutes+1)]
def enqueue(t, robots, resources): def enqueue(t, robots, resources):
if t < 0 or t >= len(buckets): assert t > 0
if t <= 0 or t >= len(buckets):
return return
#x = (resources[3], max(resources[3], robots[3]), max(resources[2], robots[2]), max(resources[1], robots[1]), max(resources[0], robots[0]))
x = resources[3] x = resources[3]
#w = sum(worth[r]*robots[robot_number[r]] for r in worth)
#x = tuple(reversed(resources+robots+[resources[3]]))
#x = (resources[3], robots)
#n = sum(x==0 for x in robots)
#if n == 3:
# x = (resources[0], robots[0])
#elif n == 2:
# x = (resources[1], resources[0], robots[1], robots[0])
#elif n == 1:
# x = (robots[3], min(resources[2],resources[0]), max(resources[2],resources[1]), robots[2], robots[1],robots[0])
#else:
# x = (resources[3], min(resources[2],resources[0]), max(resources[2],resources[0]), resources[1])
buckets[t].append((x,robots, resources)) buckets[t].append((x,robots, resources))
enqueue(minutes, robots, resources) enqueue(minutes, robots=[1,0,0,0], resources=[0,0,0,0])
del resources
del robots
max_geodes = 0 max_geodes = 0
for _ in range(minutes): for _ in range(minutes):
#next = [[] for _ in range(4)]
buckets[minutes].sort(reverse=True) buckets[minutes].sort(reverse=True)
print(minutes, buckets[minutes][:1]) #print(minutes, buckets[minutes][:1])
for _, robots, resources in buckets[minutes][:100000]: for _, robots, resources in buckets[minutes][:limit]:
can_build = 0
if robots[3]: if robots[3]:
geodes = robots[3]*minutes + resources[3] geodes = robots[3]*minutes + resources[3]
if geodes > max_geodes: if geodes > max_geodes:
max_geodes = geodes max_geodes = geodes
for robot, cost in B_items: for robot, cost in items:
i = robot_number[robot] i = robot_number[robot]
if robots[i] >= rmax[i]: if robots[i] >= rmax[i]:
# don't build more of 1 robot than we can spend in 1 minute # don't build more of 1 robot than we can spend in 1 minute
@ -103,40 +76,21 @@ def simulate(blueprint, minutes=24):
break break
if y > x: if y > x:
wait = max(wait, int(math.ceil((y - x)/r))) wait = max(wait, int(math.ceil((y - x)/r)))
if wait > minutes: if wait+1 >= minutes:
continue continue
new_resources = [x+(wait+1)*r-y for x,y,r in zip(resources, cost, robots)] new_resources = [x+(wait+1)*r-y for x,y,r in zip(resources, cost, robots)]
if robot != 'nothing':
new_robots = list(robots) new_robots = list(robots)
new_robots[i] += 1 new_robots[i] += 1
else:
new_robots = robots
enqueue(minutes-wait-1, new_robots, new_resources) enqueue(minutes-wait-1, new_robots, new_resources)
#print(len(next))
#limit = 2500 print(minutes, max_geodes, [len(x) for x in buckets[:minutes+1]])
buckets[minutes] = [] # clear old buckets to save memory
#q = []
#for bucket in next:
# bucket.sort(reverse=True)
# q.extend(bucket[:limit])
#count = sum(len(b) for b in next)
#print(count, q[:1])
print(minutes, [len(x) for x in buckets])
buckets[minutes] = []
minutes -= 1 minutes -= 1
#print(buckets)
#q = buckets[0]
#print(q[0])
#return q[0][-1][-1]
return max_geodes return max_geodes
#simulate(blueprints[1])
input = {} input = {}
with open('input') as f: with open('input') as f:
for line in f: for line in f:
@ -148,7 +102,7 @@ def solve(input):
for idx, B in input.items(): for idx, B in input.items():
g = simulate(B) g = simulate(B)
t += idx*g t += idx*g
print(idx, g) print("blueprint", idx, "max geodes is", g)
print("---") print("---")
print(t) print(t)
return t return t
@ -162,6 +116,7 @@ def solve2(input):
print(t) print(t)
return t return t
#assert solve(sample) == 33 assert solve(sample) == 33
#solve(input)
solve2(input) solve2(input)