From 25a44b35449b3340c120025506173b85e3e708ea Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Mon, 19 Dec 2022 09:13:31 +0100 Subject: [PATCH] day19 - unfinished, but cannot ignore work :/ --- day19.py | 159 ++++++++++++++++++++++++++++++++++++++++++++ inputs/input19 | 30 +++++++++ inputs/input19_test | 2 + 3 files changed, 191 insertions(+) create mode 100644 day19.py create mode 100644 inputs/input19 create mode 100644 inputs/input19_test diff --git a/day19.py b/day19.py new file mode 100644 index 0000000..2416747 --- /dev/null +++ b/day19.py @@ -0,0 +1,159 @@ +from enum import Enum +from tools.aoc import AOCDay +from typing import Any + + +class Material(Enum): + ORE = 1 + CLAY = 2 + OBSIDIAN = 3 + GEODE = 4 + + +class Robot: + def __init__(self, produces: Material, costs: dict): + self.produces = produces + self.costs = costs + + +class Blueprint: + def __init__(self, bp_id: int, robots: dict): + self.bp_id = bp_id + self.robots = robots + + +class Inventory: + def __init__(self): + self.robots = { + Material.ORE: 1, + Material.CLAY: 0, + Material.OBSIDIAN: 0, + Material.GEODE: 0, + } + self.materials = { + Material.ORE: 0, + Material.CLAY: 0, + Material.OBSIDIAN: 0, + Material.GEODE: 0, + } + self.build_queue = [] + + def gather(self) -> None: + for mat, amount in self.robots.items(): + self.materials[mat] += amount + + def queue_build_robot(self, robot: Robot) -> None: + for cost_mat, cost_amount in robot.costs.items(): + self.materials[cost_mat] -= cost_amount + self.build_queue.append(robot) + + def build_queued_robots(self) -> None: + for robot in self.build_queue: + self.robots[robot.produces] += 1 + self.build_queue = [] + + def build_robot(self, robot: Robot) -> None: + self.queue_build_robot(robot) + self.build_queued_robots() + + def copy(self) -> 'Inventory': + new_inv = Inventory() + new_inv.robots = self.robots.copy() + new_inv.materials = self.materials.copy() + return new_inv + + +def pass_minute(bp: Blueprint, inv: Inventory, ignore: list) -> list: + could_build = [] + for mat in Material: + for robot_mat, robot_cost in bp.robots[mat].costs.items(): + if inv.materials[robot_mat] < robot_cost: + break + else: + if bp.robots[mat] not in ignore: + could_build.append(bp.robots[mat]) + + inv.gather() + + return could_build + + +def get_quality(bp: Blueprint, inv: Inventory, ignore: list, time_left: int = 24, min_geode: int = 0) -> (int, int): + #print("get_quality", time_left, inv.materials, inv.robots) + for m in range(time_left): + 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): + max_quality = 0 + for robot in could_build: + sub_inv = inv.copy() + sub_inv.build_robot(robot) + sub_quality, sub_min_geode = get_quality(bp, sub_inv, [], time_left - m - 1, min_geode) + if sub_quality > max_quality: + max_quality = sub_quality + if sub_min_geode > min_geode: + min_geode = sub_min_geode + + sub_quality, sub_min_geode = get_quality(bp, inv, could_build, time_left - m - 1, min_geode) + if sub_quality > max_quality: + max_quality = sub_quality + if sub_min_geode > min_geode: + min_geode = sub_min_geode + + return max_quality, min_geode + + return inv.materials[Material.GEODE], min_geode + + +class Day(AOCDay): + inputs = [ + [ + (33, "input19_test"), + (None, "input19"), + ], + [ + (None, "input19"), + ] + ] + + def get_blueprints(self) -> list: + bp = [] + for line in self.getInput(): + parts = line.split(" ") + blueprint_id = int(parts[1][:-1]) + ore_ore_cost = int(parts[6]) + clay_ore_cost = int(parts[12]) + obsi_ore_cost = int(parts[18]) + obsi_clay_cost = int(parts[21]) + geode_ore_cost = int(parts[27]) + geode_obsi_cost = int(parts[30]) + robots = { + Material.ORE: Robot(Material.ORE, {Material.ORE: ore_ore_cost}), + Material.CLAY: Robot(Material.CLAY, {Material.ORE: clay_ore_cost}), + Material.OBSIDIAN: Robot(Material.OBSIDIAN, {Material.ORE: obsi_ore_cost, Material.CLAY: obsi_clay_cost}), + Material.GEODE: Robot(Material.GEODE, {Material.ORE: geode_ore_cost, Material.OBSIDIAN: geode_obsi_cost}) + } + bp.append(Blueprint(blueprint_id, robots)) + + return bp + + def part1(self) -> Any: + blueprints = self.get_blueprints() + #for b in blueprints: + b = blueprints[0] + print("BP", b.bp_id, "Q", get_quality(b, Inventory(), [], 24)) + b = blueprints[1] + print("BP", b.bp_id, "Q", get_quality(b, Inventory(), [], 24)) + return "" + + def part2(self) -> Any: + return "" + + +if __name__ == '__main__': + day = Day(2022, 19) + day.run(verbose=True) diff --git a/inputs/input19 b/inputs/input19 new file mode 100644 index 0000000..b7b2f69 --- /dev/null +++ b/inputs/input19 @@ -0,0 +1,30 @@ +Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian. +Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 2 ore and 13 obsidian. +Blueprint 3: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 14 obsidian. +Blueprint 4: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 2 ore and 14 obsidian. +Blueprint 5: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 2 ore and 10 obsidian. +Blueprint 6: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 4 ore and 11 obsidian. +Blueprint 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 3 ore and 15 obsidian. +Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 10 clay. Each geode robot costs 2 ore and 7 obsidian. +Blueprint 9: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 9 obsidian. +Blueprint 10: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 2 ore and 18 obsidian. +Blueprint 11: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 10 obsidian. +Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 10 clay. Each geode robot costs 4 ore and 10 obsidian. +Blueprint 13: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 3 ore and 14 obsidian. +Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 4 ore and 13 obsidian. +Blueprint 15: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 8 obsidian. +Blueprint 16: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 3 ore and 8 obsidian. +Blueprint 17: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 8 obsidian. +Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 3 ore and 11 obsidian. +Blueprint 19: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 3 ore and 18 obsidian. +Blueprint 20: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 4 ore and 11 obsidian. +Blueprint 21: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 19 obsidian. +Blueprint 22: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 2 ore and 12 obsidian. +Blueprint 23: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 13 obsidian. +Blueprint 24: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 8 obsidian. +Blueprint 25: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 2 ore and 9 obsidian. +Blueprint 26: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 2 ore and 14 obsidian. +Blueprint 27: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 10 obsidian. +Blueprint 28: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 16 obsidian. +Blueprint 29: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 17 obsidian. +Blueprint 30: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 20 obsidian. diff --git a/inputs/input19_test b/inputs/input19_test new file mode 100644 index 0000000..f39c094 --- /dev/null +++ b/inputs/input19_test @@ -0,0 +1,2 @@ +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. +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.