diff --git a/day19/sol.py b/day19/sol.py index 09f89f4..692d146 100644 --- a/day19/sol.py +++ b/day19/sol.py @@ -1,21 +1,22 @@ - import math import re + sample = { 1:{ - 'ore': [4, 0, 0, 0], - 'clay': [2, 0, 0, 0], - 'obsidian': [3, 14, 0, 0], - 'geode': [2, 0, 7, 0], -}, - 2:{ - 'ore': [2, 0, 0, 0], - 'clay': [3, 0, 0, 0], - 'obsidian': [3, 8, 0, 0], - 'geode': [3, 0, 12, 0], -}} + 'ore': [4, 0, 0, 0], + 'clay': [2, 0, 0, 0], + 'obsidian': [3, 14, 0, 0], + 'geode': [2, 0, 7, 0], + }, + 2: { + 'ore': [2, 0, 0, 0], + 'clay': [3, 0, 0, 0], + 'obsidian': [3, 8, 0, 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): line = re.sub(r'[^\d]+', ' ', line) @@ -28,66 +29,38 @@ def parse(line): } def simulate(blueprint, minutes=24): - B = blueprint - resources = [0]*4 - robots = [1,0,0,0] - - rmax = [max(x[i] for x in B.values()) for i in range(3)] + [99] + rmax = [max(x[i] for x in blueprint.values()) for i in range(3)] + [9999] + limit = None + if minutes >= 32: + limit = 100000 - worth = {} - 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] + items = list(blueprint.items()) + items.reverse() - print(worth) - - - B_items = list(B.items()) - B_items.reverse() - - #B_items.append(('nothing', [0,0,0,0])) - - print(B_items) + print(items) buckets = [[] for _ in range(minutes+1)] def enqueue(t, robots, resources): - if t < 0 or t >= len(buckets): + assert t > 0 + if t <= 0 or t >= len(buckets): 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] - #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)) - enqueue(minutes, robots, resources) - del resources - del robots + enqueue(minutes, robots=[1,0,0,0], resources=[0,0,0,0]) max_geodes = 0 - + for _ in range(minutes): - #next = [[] for _ in range(4)] buckets[minutes].sort(reverse=True) - print(minutes, buckets[minutes][:1]) - for _, robots, resources in buckets[minutes][:100000]: - can_build = 0 + #print(minutes, buckets[minutes][:1]) + for _, robots, resources in buckets[minutes][:limit]: if robots[3]: geodes = robots[3]*minutes + resources[3] if geodes > max_geodes: max_geodes = geodes - for robot, cost in B_items: + for robot, cost in items: i = robot_number[robot] if robots[i] >= rmax[i]: # don't build more of 1 robot than we can spend in 1 minute @@ -103,39 +76,20 @@ def simulate(blueprint, minutes=24): break if y > x: wait = max(wait, int(math.ceil((y - x)/r))) - if wait > minutes: + if wait+1 >= minutes: continue 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[i] += 1 - else: - new_robots = robots + new_robots = list(robots) + new_robots[i] += 1 enqueue(minutes-wait-1, new_robots, new_resources) - #print(len(next)) - #limit = 2500 - - #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] = [] + print(minutes, max_geodes, [len(x) for x in buckets[:minutes+1]]) + buckets[minutes] = [] # clear old buckets to save memory minutes -= 1 - #print(buckets) - #q = buckets[0] - #print(q[0]) - #return q[0][-1][-1] return max_geodes - -#simulate(blueprints[1]) input = {} with open('input') as f: @@ -148,7 +102,7 @@ def solve(input): for idx, B in input.items(): g = simulate(B) t += idx*g - print(idx, g) + print("blueprint", idx, "max geodes is", g) print("---") print(t) return t @@ -162,6 +116,7 @@ def solve2(input): print(t) return t -#assert solve(sample) == 33 +assert solve(sample) == 33 +#solve(input) solve2(input)