diff --git a/day19/sol.py b/day19/sol.py index 692d146..471edf4 100644 --- a/day19/sol.py +++ b/day19/sol.py @@ -56,15 +56,36 @@ def simulate(blueprint, minutes=24): buckets[minutes].sort(reverse=True) #print(minutes, buckets[minutes][:1]) for _, robots, resources in buckets[minutes][:limit]: - if robots[3]: + if 1: geodes = robots[3]*minutes + resources[3] if geodes > max_geodes: max_geodes = geodes + elif geodes < max_geodes: + # if the number of geodes we could get if we stopped building robots + # is less than the max such number we've seen so far, + # then prune this node. + # + # this seems like it would be too greedy a rule, but + # somehow it actually works. (i think this is equivalant to + # the rule "always build a geode robot as soon as you can" + # and its validity depends on the input data. (in fact it + # *doesn't* work for the first sample blueprint for part 2. + # but it works on my input so w/e) + # + # decreases the search space enormously + continue 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 continue + if robot != 'geode' and robots[i]*minutes + resources[i] >= minutes*rmax[i]: + # insight from reddit: if we have enough resources on hand and enough + # mining capacity to build any robot that needs it every turn until + # time is up, then we don't need to build any more of that kind of robot + # + # this provides a minor speed-up over just doing the simpler check + continue # figure out how soon we can afford it wait = 0 @@ -117,6 +138,6 @@ def solve2(input): return t assert solve(sample) == 33 -#solve(input) +solve(input) solve2(input)