day19 - did solve p1; very, very slowly; doesn't solve p2

This commit is contained in:
Stefan Harmuth 2022-12-19 17:28:12 +01:00
parent 25a44b3544
commit f6f677ae5a

View File

@ -11,9 +11,10 @@ class Material(Enum):
class Robot: class Robot:
def __init__(self, produces: Material, costs: dict): def __init__(self, produces: Material, costs: dict, min_viable: int = 0):
self.produces = produces self.produces = produces
self.costs = costs self.costs = costs
self.min_viable = min_viable
class Blueprint: class Blueprint:
@ -36,7 +37,7 @@ class Inventory:
Material.OBSIDIAN: 0, Material.OBSIDIAN: 0,
Material.GEODE: 0, Material.GEODE: 0,
} }
self.build_queue = [] self.__build_queue = []
def gather(self) -> None: def gather(self) -> None:
for mat, amount in self.robots.items(): for mat, amount in self.robots.items():
@ -45,12 +46,12 @@ class Inventory:
def queue_build_robot(self, robot: Robot) -> None: def queue_build_robot(self, robot: Robot) -> None:
for cost_mat, cost_amount in robot.costs.items(): for cost_mat, cost_amount in robot.costs.items():
self.materials[cost_mat] -= cost_amount self.materials[cost_mat] -= cost_amount
self.build_queue.append(robot) self.__build_queue.append(robot)
def build_queued_robots(self) -> None: def build_queued_robots(self) -> None:
for robot in self.build_queue: for robot in self.__build_queue:
self.robots[robot.produces] += 1 self.robots[robot.produces] += 1
self.build_queue = [] self.__build_queue = []
def build_robot(self, robot: Robot) -> None: def build_robot(self, robot: Robot) -> None:
self.queue_build_robot(robot) self.queue_build_robot(robot)
@ -63,7 +64,7 @@ class Inventory:
return new_inv return new_inv
def pass_minute(bp: Blueprint, inv: Inventory, ignore: list) -> list: def pass_minute(bp: Blueprint, inv: Inventory, ignore: list) -> (Inventory, list):
could_build = [] could_build = []
for mat in Material: for mat in Material:
for robot_mat, robot_cost in bp.robots[mat].costs.items(): for robot_mat, robot_cost in bp.robots[mat].costs.items():
@ -75,47 +76,44 @@ def pass_minute(bp: Blueprint, inv: Inventory, ignore: list) -> list:
inv.gather() inv.gather()
return could_build return inv, could_build
def get_quality(bp: Blueprint, inv: Inventory, ignore: list, time_left: int = 24, min_geode: int = 0) -> (int, int): def get_quality(bp: Blueprint, inv: Inventory, ignore: list, time_left: int = 24) -> int:
#print("get_quality", time_left, inv.materials, inv.robots)
for m in range(time_left): for m in range(time_left):
could_build = pass_minute(bp, inv, ignore) inv, could_build = pass_minute(bp, inv, ignore)
if bp.robots[Material.GEODE] in could_build and time_left - m > min_geode:
min_geode = time_left - m
print("Can build Geode Robot with", min_geode, "min left.")
print(inv.robots, inv.materials)
if could_build and time_left - m > 1 and (inv.robots[Material.GEODE] > 0 or time_left > min_geode): if could_build and time_left - m > 1:
max_quality = 0 max_quality = 0
build_a_bot = False
for robot in could_build: for robot in could_build:
if robot.min_viable > time_left - m:
continue
sub_inv = inv.copy() sub_inv = inv.copy()
sub_inv.build_robot(robot) sub_inv.build_robot(robot)
sub_quality, sub_min_geode = get_quality(bp, sub_inv, [], time_left - m - 1, min_geode) sub_quality = get_quality(bp, sub_inv, [], time_left - m - 1)
if sub_quality > max_quality: if sub_quality > max_quality:
max_quality = sub_quality max_quality = sub_quality
if sub_min_geode > min_geode: build_a_bot = True
min_geode = sub_min_geode
sub_quality, sub_min_geode = get_quality(bp, inv, could_build, time_left - m - 1, min_geode) if build_a_bot:
if sub_quality > max_quality: sub_quality = get_quality(bp, inv, could_build, time_left - m - 1)
max_quality = sub_quality if sub_quality > max_quality:
if sub_min_geode > min_geode: max_quality = sub_quality
min_geode = sub_min_geode
return max_quality, min_geode return max_quality
return inv.materials[Material.GEODE], min_geode return inv.materials[Material.GEODE]
class Day(AOCDay): class Day(AOCDay):
inputs = [ inputs = [
[ [
(33, "input19_test"), (33, "input19_test"),
(None, "input19"), (1616, "input19"),
], ],
[ [
(56*62, "input19_test"),
(None, "input19"), (None, "input19"),
] ]
] ]
@ -132,10 +130,10 @@ class Day(AOCDay):
geode_ore_cost = int(parts[27]) geode_ore_cost = int(parts[27])
geode_obsi_cost = int(parts[30]) geode_obsi_cost = int(parts[30])
robots = { robots = {
Material.ORE: Robot(Material.ORE, {Material.ORE: ore_ore_cost}), Material.ORE: Robot(Material.ORE, {Material.ORE: ore_ore_cost}, 7),
Material.CLAY: Robot(Material.CLAY, {Material.ORE: clay_ore_cost}), Material.CLAY: Robot(Material.CLAY, {Material.ORE: clay_ore_cost}, 5),
Material.OBSIDIAN: Robot(Material.OBSIDIAN, {Material.ORE: obsi_ore_cost, Material.CLAY: obsi_clay_cost}), Material.OBSIDIAN: Robot(Material.OBSIDIAN, {Material.ORE: obsi_ore_cost, Material.CLAY: obsi_clay_cost}, 3),
Material.GEODE: Robot(Material.GEODE, {Material.ORE: geode_ore_cost, Material.OBSIDIAN: geode_obsi_cost}) Material.GEODE: Robot(Material.GEODE, {Material.ORE: geode_ore_cost, Material.OBSIDIAN: geode_obsi_cost}, 1)
} }
bp.append(Blueprint(blueprint_id, robots)) bp.append(Blueprint(blueprint_id, robots))
@ -143,15 +141,21 @@ class Day(AOCDay):
def part1(self) -> Any: def part1(self) -> Any:
blueprints = self.get_blueprints() blueprints = self.get_blueprints()
#for b in blueprints: score = 0
b = blueprints[0] for b in blueprints:
print("BP", b.bp_id, "Q", get_quality(b, Inventory(), [], 24)) quality = get_quality(b, Inventory(), [])
b = blueprints[1] print("BP", b.bp_id, "Q", quality)
print("BP", b.bp_id, "Q", get_quality(b, Inventory(), [], 24)) score += quality * b.bp_id
return "" return score
def part2(self) -> Any: def part2(self) -> Any:
return "" blueprints = self.get_blueprints()
score = 1
for b in blueprints[:3]:
quality = get_quality(b, Inventory(), [], 32)
print("BP", b.bp_id, "Q", quality)
score *= quality
return score
if __name__ == '__main__': if __name__ == '__main__':