day19 - p2 in sub 3min; still to be improved

This commit is contained in:
Stefan Harmuth 2022-12-21 16:18:50 +01:00
parent 265f481472
commit 6fdf2d55ff

View File

@ -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