|
| 1 | +import string |
| 2 | +from collections import defaultdict |
| 3 | +from aoc_tools import * |
| 4 | +import functools |
| 5 | +import sys |
| 6 | +#sys.setrecursionlimit(10000000) |
| 7 | +dirs = ((0,1),(1,0),(0,-1),(-1,0)) |
| 8 | +dirs3 = ((1,0,0),(-1,0,0),(0,1,0),(0,-1,0),(0,0,1),(0,0,-1)) |
| 9 | + |
| 10 | +with open(r"input.txt") as f: |
| 11 | + s = f.read().strip() |
| 12 | +print("\n".join(x[:60] for x in s.split("\n")[:6])) |
| 13 | + |
| 14 | +s = """Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian. |
| 15 | +Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.""" |
| 16 | + |
| 17 | + |
| 18 | +mp = {"ore":0,"clay":1,"obsidian":2} |
| 19 | +all_r = [] |
| 20 | +for jj,l in enumerate(s.split("\n")): |
| 21 | + r = l.split(": ")[1] |
| 22 | + r = r.strip(".").split(". ") |
| 23 | + r = [x[5:] for x in r] |
| 24 | + r = [x.split(" costs ") for x in r] |
| 25 | + r = [(rt, tuple((int(n), mp[t]) for it in recipe.split(" and ") |
| 26 | + for n,t in [it.split(" ")] |
| 27 | + )) for rt,recipe in r] |
| 28 | + all_r.append((jj + 1, r)) |
| 29 | + |
| 30 | +all_pruned_r = [] |
| 31 | +for i,(idx,r1) in enumerate(all_r): |
| 32 | + dominates = True |
| 33 | + for _,r2 in all_r[i+1:]: |
| 34 | + # check if r2 dominates r1 |
| 35 | + for (_, rec1), (_, rec2) in zip(r1,r2): |
| 36 | + if any(qty1 < qty2 for (_,qty1),(_,qty2) in zip(rec1,rec2)): |
| 37 | + dominates = False |
| 38 | + break |
| 39 | + if not dominates: |
| 40 | + print(f"{i} is dominated!") |
| 41 | + else: |
| 42 | + all_pruned_r.append((idx,r1)) |
| 43 | + |
| 44 | +for rnum,r in all_pruned_r: |
| 45 | + print("checking bot", rnum) |
| 46 | + print(r) |
| 47 | + |
| 48 | + # dp[#ore,#clay,#obs,#geo,t] = max value we can get |
| 49 | + |
| 50 | + rlimits = [0,0,0] |
| 51 | + for _, recipe in r: |
| 52 | + for qty,typ in recipe: |
| 53 | + rlimits[typ] = max(rlimits[typ],qty) |
| 54 | + |
| 55 | + global bbv |
| 56 | + bbv = 0 |
| 57 | + |
| 58 | + dominated_on_12 = [] |
| 59 | + dominated_on_14 = [] |
| 60 | + |
| 61 | + @functools.lru_cache(maxsize=None) |
| 62 | + def solve(resources, robots, t_left): |
| 63 | + global bbv |
| 64 | + |
| 65 | + if t_left == 12: |
| 66 | + for dresources, drobots in dominated_on_12: |
| 67 | + if all(dresources[i] >= resources[i] for i in range(3)) and ( |
| 68 | + all(drobots[i] >= robots[i] for i in range(4))): |
| 69 | + print("PRUNED12!") |
| 70 | + return 0 |
| 71 | + dominated_on_12.append((resources, robots)) |
| 72 | + |
| 73 | + if t_left == 14: |
| 74 | + for dresources, drobots in dominated_on_14: |
| 75 | + if all(dresources[i] >= resources[i] for i in range(3)) and ( |
| 76 | + all(drobots[i] >= robots[i] for i in range(4))): |
| 77 | + print("PRUNED14!") |
| 78 | + return 0 |
| 79 | + dominated_on_14.append((resources, robots)) |
| 80 | + |
| 81 | + if t_left >= 12: |
| 82 | + print(t_left, resources, robots) |
| 83 | + #global d |
| 84 | + #d += 1 |
| 85 | + #if d % 10000 == 0: |
| 86 | + # print(resources, robots, t_left,cb) |
| 87 | + # resources is 3-tuple |
| 88 | + # robots is 4-tuple |
| 89 | + new_resources = list(resources) |
| 90 | + |
| 91 | + bv = 0 |
| 92 | + |
| 93 | + # if at this point, we can build 1 of every robot, we made a mistake |
| 94 | + if robots[1] == 0: |
| 95 | + # if we haven't built a clay, and we have at least enough ore to |
| 96 | + # build a clay or ore bot, just do it |
| 97 | + if resources[0] >= rlimits[0]: |
| 98 | + return 0 |
| 99 | + elif robots[2] == 0: |
| 100 | + # if we haven't built an obsidian, and have enough to build |
| 101 | + if resources[0] >= rlimits[0] and resources[1] > rlimits[1]: |
| 102 | + return 0 |
| 103 | + elif all(resources[i] >= rlimits[i] for i in range(3)): |
| 104 | + return 0 |
| 105 | + |
| 106 | + v = 0 |
| 107 | + for i in range(3): |
| 108 | + new_resources[i] += robots[i] |
| 109 | + v += robots[3] |
| 110 | + |
| 111 | + if t_left == 1: |
| 112 | + return v |
| 113 | + |
| 114 | +## max_builds = [ |
| 115 | +## min(resources[typ]//qty for qty,typ in r[j][1]) |
| 116 | +## for j in range(4) |
| 117 | +## ] |
| 118 | + |
| 119 | + for i in range(4): |
| 120 | + # can we build robot of type i? |
| 121 | + if all(resources[typ] >= qty for qty,typ in r[i][1]): |
| 122 | + # try building robot of type i? |
| 123 | + new_new_resources = new_resources.copy() |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | +## for built_num2 in range(max_builds[-1],-1,-1): |
| 128 | +## for built_num in itertools.product(*[range(max_build,-1,-1) for max_build in |
| 129 | +## max_builds[:3]]): |
| 130 | +## built_num = built_num + (built_num2,) |
| 131 | +## new_new_resources = new_resources.copy() |
| 132 | +## for i in range(4): |
| 133 | +## for qty, typ in r[i][1]: |
| 134 | +## new_new_resources[typ] -= qty * built_num[i] |
| 135 | +## if min(new_new_resources) < 0: |
| 136 | +## continue |
| 137 | +## |
| 138 | +## new_robots = list(robots) |
| 139 | +## for i in range(4): |
| 140 | +## new_robots[i] += built_num[i] |
| 141 | +## bv = max(bv, v + solve(tuple(new_new_resources), |
| 142 | +## tuple(new_robots), |
| 143 | +## t_left - 1)) |
| 144 | + if bv > bbv: |
| 145 | + print("MAX:",bv) |
| 146 | + bbv = bv |
| 147 | + return bv |
| 148 | + |
| 149 | +## ONLY_ORE = 6 |
| 150 | +## ore_cnt = 0 |
| 151 | +## ore_rbt = 1 |
| 152 | +## for i in range(ONLY_ORE): |
| 153 | +## n = 0 |
| 154 | +## if ore_cnt >= r[0][1][0][0]: |
| 155 | +## n += ore_cnt // r[0][1][0][0] |
| 156 | +## ore_cnt -= n * r[0][1][0][0] |
| 157 | +## ore_cnt += ore_rbt |
| 158 | +## ore_rbt += n |
| 159 | +## print(ore_cnt, ore_rbt) |
| 160 | + |
| 161 | + import time |
| 162 | + st = time.time() |
| 163 | + print(solve((0,0,0),(1,0,0,0),24)) |
| 164 | + #print(solve((ore_cnt,0,0),(ore_rbt,0,0,0), 24 - ONLY_ORE)) |
| 165 | + et = time.time() |
| 166 | + print(et - st) |
| 167 | + break |
| 168 | + |
| 169 | + |
| 170 | + |
| 171 | + |
| 172 | + |
| 173 | + |
| 174 | + |
| 175 | + |
| 176 | + |
| 177 | + |
| 178 | + |
| 179 | + |
| 180 | + |
| 181 | + |
| 182 | + |
| 183 | + |
| 184 | + |
| 185 | + |
| 186 | + |
| 187 | + |
| 188 | + |
| 189 | + |
| 190 | + |
| 191 | + |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | + |
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | + |
| 200 | + |
| 201 | + |
| 202 | + |
| 203 | + |
| 204 | + |
| 205 | + |
| 206 | + |
| 207 | + |
| 208 | + |
| 209 | + |
| 210 | + |
| 211 | + |
| 212 | + |
| 213 | + |
| 214 | + |
| 215 | + |
| 216 | + |
0 commit comments