diff --git a/day19.py b/day19.py index 65805e3..e132e03 100644 --- a/day19.py +++ b/day19.py @@ -1,10 +1,9 @@ +from collections import defaultdict from enum import Enum from heapq import heappush, heappop from tools.aoc import AOCDay from typing import Any -from tools.int_seq import triangular - class Material(Enum): ORE = 1 @@ -51,6 +50,12 @@ class Inventory: new_inv.materials = self.materials.copy() return new_inv + def value(self) -> int: + return self.robots[Material.ORE] \ + + 2 * self.robots[Material.CLAY] \ + + 4 * self.robots[Material.OBSIDIAN] \ + + 8 * self.robots[Material.GEODE] + def __lt__(self, other: 'Inventory') -> bool: return self.materials[Material.GEODE] < other.materials[Material.GEODE] @@ -84,21 +89,33 @@ def pass_minute(bp: Blueprint, inv: Inventory, ignore: list) -> (Inventory, list return inv, could_build -def get_bfs_quality(bp: Blueprint, max_time: int = 24) -> int: +def get_dfs_quality(bp: Blueprint, max_time: int = 24) -> int: q = [] max_geode = 0 + max_value = defaultdict(int) heappush(q, (max_time, Inventory(), [], 0)) + q_count = 0 while q: + q_count += 1 time_left, inv, ignore, no_build = heappop(q) - inv, could_build = pass_minute(bp, inv, ignore) time_left -= 1 + inv_value = inv.value() + if inv_value < max_value[time_left] // 2.1: + continue + elif inv_value > max_value[time_left]: + max_value[time_left] = inv_value if time_left == 0: if inv.materials[Material.GEODE] > max_geode: max_geode = inv.materials[Material.GEODE] continue + if bp.robots[Material.GEODE] in could_build: + inv.build_robot(bp.robots[Material.GEODE]) + heappush(q, (time_left, inv, [], 0)) + continue + for robot in could_build: if robot.min_viable > time_left: continue @@ -109,6 +126,7 @@ def get_bfs_quality(bp: Blueprint, max_time: int = 24) -> int: if no_build < bp.max_cost[Material.ORE]: heappush(q, (time_left, inv, could_build, no_build + 1)) + print(q_count) return max_geode @@ -119,7 +137,7 @@ class Day(AOCDay): (1616, "input19"), ], [ - #(56*62, "input19_test"), + (3472, "input19_test"), (8990, "input19"), ] ] @@ -149,7 +167,7 @@ class Day(AOCDay): blueprints = self.get_blueprints() score = 0 for b in blueprints: - quality = get_bfs_quality(b) + quality = get_dfs_quality(b) score += quality * b.bp_id print("BP", b.bp_id, "Q", quality, "S", score) return score @@ -158,7 +176,7 @@ class Day(AOCDay): blueprints = self.get_blueprints() score = 1 for b in blueprints[:3]: - quality = get_bfs_quality(b, 32) + quality = get_dfs_quality(b, 32) score *= quality print("BP", b.bp_id, "Q", quality, "S", score) return score