diff --git a/day19/sol.py b/day19/sol.py index 1936816..36fa717 100644 --- a/day19/sol.py +++ b/day19/sol.py @@ -1,4 +1,5 @@ +import math import re sample = { 1:{ @@ -46,71 +47,93 @@ def simulate(blueprint): B_items = list(B.items()) B_items.reverse() - B_items.append(('nothing', [0,0,0,0])) + #B_items.append(('nothing', [0,0,0,0])) print(B_items) minutes = 24 - q = [(0, robots, resources)] + buckets = [[] for _ in range(minutes+1)] + def enqueue(t, robots, resources): + 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 + + max_geodes = 0 + for _ in range(minutes): - next = [[] for _ in range(4)] - for _, robots, resources in q: + #next = [[] for _ in range(4)] + buckets[minutes].sort(reverse=True) + print(minutes, buckets[minutes][:1]) + for _, robots, resources in buckets[minutes]: can_build = 0 + if robots[3]: + geodes = robots[3]*minutes + resources[3] + if geodes > max_geodes: + max_geodes = geodes for robot, cost in B_items: i = robot_number[robot] - if robot != 'nothing' and robots[i] >= rmax[i]: + if robots[i] >= rmax[i]: # don't build more of 1 robot than we can spend in 1 minute continue - if robot == 'nothing' and can_build == 3: - # always build something unless - continue - if not all(x >= y for x, y in zip(resources, cost)): - # can't afford + + # figure out how soon we can afford it + wait = 0 + for x,y,r in zip(resources, cost, robots): + if y == 0: + continue + if r <= 0: + wait = 9999 + break + if y > x: + wait = max(wait, int(math.ceil((y - x)/r))) + if wait > minutes: continue - new = [] - for x,y,z,m in zip(resources, robots, cost, rmax): - x = x+y-z - new.append(x) + 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 - x = (new[3], max(new[3], new_robots[3]), max(new[2], new_robots[2]), max(new[1], new_robots[1]), max(new[0], new_robots[0])) - #w = sum(worth[r]*robots[robot_number[r]] for r in worth) - #x = tuple(reversed(new+new_robots+[new[3]])) - #x = (new[3], new_robots) - n = sum(x==0 for x in new_robots) - if n == 3: - x = (new[0], new_robots[0]) - elif n == 2: - x = (new[1], new[0], new_robots[1], new_robots[0]) - elif n == 1: - x = (new_robots[3], min(new[2],new[0]), max(new[2],new[1]), new_robots[2], new_robots[1],new_robots[0]) - else: - x = (new[3], min(new[2],new[0]), max(new[2],new[0]), new[1]) - next[n].append((x,new_robots,new)) - can_build += 1 - if robot == 'geode': - # if we can build a geode then don't bother building anything else - break + enqueue(minutes-wait-1, new_robots, new_resources) #print(len(next)) - limit = 2500 + #limit = 2500 - q = [] - for bucket in next: - bucket.sort(reverse=True) - q.extend(bucket[:limit]) + #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]) + #count = sum(len(b) for b in next) + #print(count, q[:1]) + print(minutes, [len(x) for x in buckets]) - print(q[0]) - return q[0][-1][-1] + minutes -= 1 + + #print(buckets) + #q = buckets[0] + #print(q[0]) + #return q[0][-1][-1] + return max_geodes #simulate(blueprints[1])