From 09d25eb6745a2e2f006d8176d509525aadf12061 Mon Sep 17 00:00:00 2001 From: Luke Hubmayer-Werner Date: Tue, 20 Dec 2022 02:09:03 +1030 Subject: [PATCH] MT optimisation --- 2022/day19.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/2022/day19.py b/2022/day19.py index aaa8b6a..2888180 100644 --- a/2022/day19.py +++ b/2022/day19.py @@ -11,27 +11,27 @@ maximum_potential = np.arange(33, dtype=np.int8).cumsum() def bp_quality(line, t_max=24): bp, cost_orebot_ore, cost_claybot_ore, cost_obsbot_ore, cost_obsbot_clay, cost_geodebot_ore, cost_geodebot_obs = line_to_numbers(line) - print(line) + # print(line) # Ore, Clay, Obsidian, Geode orebot_cost = np.array([cost_orebot_ore, 0, 0], dtype=np.int8) claybot_cost = np.array([cost_claybot_ore, 0, 0], dtype=np.int8) obsbot_cost = np.array([cost_obsbot_ore, cost_obsbot_clay, 0], dtype=np.int8) geodebot_cost = np.array([cost_geodebot_ore, 0, cost_geodebot_obs], dtype=np.int8) robot_orders = ( # Special ordering to try and hit best case earliest - ((0,1,0), claybot_cost), - ((1,0,0), orebot_cost), - ((0,0,1), obsbot_cost), + (1, claybot_cost), + (0, orebot_cost), + (2, obsbot_cost), (None, geodebot_cost), ) max_robots = np.array([max(cost_orebot_ore, cost_claybot_ore, cost_obsbot_ore, cost_geodebot_ore), cost_obsbot_clay, cost_geodebot_obs], dtype=np.int8) search_stack = [] - SEEN = set() + seen = set() def add_state(t, robot_counts, res_counts, geodes_total): state = (t, tuple(robot_counts), tuple(res_counts), geodes_total) - if state not in SEEN: + if state not in seen: search_stack.append((t, robot_counts, res_counts, geodes_total)) - SEEN.add(state) + seen.add(state) add_state(0, np.array((1,0,0), dtype=np.int8), np.array((0,0,0), dtype=np.int8), 0) geodes_best = 0 @@ -40,12 +40,12 @@ def bp_quality(line, t_max=24): if t < t_max: if (geodes_total + maximum_potential[t_max-t]) < geodes_best: continue - for inc, cost in robot_orders: - next_robots = robot_counts - if inc: - next_robots = robot_counts + inc - if np.any(next_robots > max_robots): + for idx, cost in robot_orders: + if idx is not None: + if robot_counts[idx] >= max_robots[idx]: continue + next_robots = robot_counts.copy() + next_robots[idx] += 1 mask = cost > 0 # Only look at resources within the cost if np.any(robot_counts[mask] == 0): # no robot no income, we can't just wait to build it continue @@ -54,25 +54,28 @@ def bp_quality(line, t_max=24): nt = t + dt if nt < t_max: # Nothing interesting can happen on the very last minute new_res = res_counts + (dt * robot_counts) - cost - if inc is None: # Special case for Geodebots + if idx is None: # Special case for Geodebots add_state(nt, robot_counts, new_res, geodes_total+(t_max-nt)) else: add_state(nt, next_robots, new_res, geodes_total) geodes_best = max(geodes_best, geodes_total) quality = bp * geodes_best - print(f'Blueprint {bp}: max geodes {geodes_best}, quality number = {quality}') + print(f'Blueprint {bp}: at {t_max} minutes: max geodes {geodes_best}, quality number = {quality}') return bp, geodes_best, quality -def p2(line): +def bp_quality32(line): return bp_quality(line, 32) if __name__ == '__main__': with Pool(8) as p: - # Maximize geodes in 24 minutes - qual_tally = sum([quality for bp, max_geodes, quality in p.map(bp_quality, lines)]) + depth32 = p.map_async(bp_quality32, lines[:3]) + depth24 = p.map_async(bp_quality, lines) + qual_tally = sum((quality for bp, max_geodes, quality in depth24.get())) print(f'Part 1: {qual_tally}') - max_prod = prod([max_geodes for bp, max_geodes, quality in p.map(p2, lines[:3])]) + max_prod = prod((max_geodes for bp, max_geodes, quality in depth32.get())) print(f'Part 2: {max_prod}') # qual_tally = sum((bp_quality(line)[-1] for line in lines)) # print(f'Part 1: {qual_tally}') + # max_prod = prod((max_geodes for bp, max_geodes, quality in map(bp_quality32, lines[:3]))) + # print(f'Part 2: {max_prod}')