diff --git a/calc2.py b/calc2.py index 1327c8e..aec92b6 100644 --- a/calc2.py +++ b/calc2.py @@ -1,4 +1,8 @@ -from functools import lru_cache, partial +from functools import lru_cache + +import pdbp # noqa: F401 + +ResourceGroup = dict[str, float] @lru_cache @@ -15,7 +19,7 @@ def dot_align(seq: tuple[float, ...], n) -> str: return _dot_align(seq)[n] -recipies: dict[str, dict[str, float]] = { +recipies: dict[str, ResourceGroup] = { # mining 'iron-ore': {'mining-drill': -1, 'iron-ore': 0.5}, 'copper-ore': {'mining-drill': -1, 'copper-ore': 0.5}, @@ -73,6 +77,7 @@ recipies: dict[str, dict[str, float]] = { 'plastic': {'chemical-plant': -1, 'coal': -1, 'petroleum-gas': -20, 'plastic': 2}, 'explosives': {'chemical-plant': -4, 'coal': -1, 'sulfur': -1, 'water': -10, 'explosives': 2}, 'battery': {'chemical-plant': -4, 'copper-plate': -1, 'iron-plate': -20, 'sulfuric-acid': -20, 'battery': 1}, + 'lubricant': {'chemical-plant': -1, 'heavy-oil': -10, 'lubricant': 10}, # military 'magazine-y': {'assembler': -1, 'iron-plate': -4, 'magazine-y': 1}, 'magazine-r': {'assembler': -1, 'copper-plate': -5, 'magazine-y': -1, 'steel': -1, 'magazine-r': 1}, @@ -151,22 +156,24 @@ recipies: dict[str, dict[str, float]] = { 'science-white': {'rocket-part': -100, 'sattelite': -1, 'science-white': 1000}, } +MACHINES = {'assembler', 'chemical-plant', 'oil-refinery'} + def get_resource_name(orig_name: str, recipe_name: str) -> str: - if orig_name in {'assembler', 'chemical-plant', 'oil-refinery'}: + if orig_name in MACHINES: return f'{orig_name}[{recipe_name}]' else: return orig_name -def add_assembler_name(recipe_name: str, resources: dict[str, float]) -> dict[str, float]: +def add_assembler_name(recipe_name: str, resources: ResourceGroup) -> ResourceGroup: return {get_resource_name(resource, recipe_name): count for resource, count in resources.items()} recipies = {name: add_assembler_name(name, resources) for name, resources in recipies.items()} -def add_recipe(targets: dict[str, float], recipe: dict[str, float], multiplier: float) -> dict[str, float]: +def add_recipe(targets: ResourceGroup, recipe: ResourceGroup, multiplier: float) -> ResourceGroup: return { resource: targets.get(resource, 0) - (multiplier * recipe.get(resource, 0)) for resource in targets.keys() | recipe.keys() @@ -174,31 +181,43 @@ def add_recipe(targets: dict[str, float], recipe: dict[str, float], multiplier: } -def compute_base_resource_flow( - targets: dict[str, float], base_resources: set[str] -) -> tuple[dict[str, float], dict[str, float]]: - results = {} +def reduce_to_base_resources(group: ResourceGroup, base: set[str]) -> tuple[ResourceGroup, ResourceGroup]: + group = group.copy() + + reduced = {} intermediates = {} - while len(targets) > 0: - resource, count = next(iter(targets.items())) + while len(group) > 0: + resource, count = next(iter(group.items())) # print(f'{resource}: {count}') - if resource in base_resources or '[' in resource: - results = add_recipe(results, {resource: count}, -1) - del targets[resource] + if resource in base or '[' in resource: + reduced = add_recipe(reduced, {resource: count}, -1) + del group[resource] continue + if resource not in recipies: + raise RuntimeError(f'{resource=} not in base or recipies') + intermediates = add_recipe(intermediates, {resource: count}, -1) recipe = recipies[resource] multiplier = count / recipe[resource] - targets = add_recipe(targets, recipe, multiplier) + group = add_recipe(group, recipe, multiplier) - return results, intermediates + return reduced, intermediates + + +def drop_machines(group: ResourceGroup) -> ResourceGroup: + return {k: v for k, v in group.items() if not k.startswith(tuple(MACHINES))} + + +def print_resource_group(group: ResourceGroup) -> None: + for resource, count in sorted(group.items()): + print(f' {resource:35}: {dot_align(tuple(group.values()), count)}') SPM = 1 -targets_groups: list[dict[str, float]] = [ +targets_groups: list[ResourceGroup] = [ {'science-red': SPM}, {'science-green': SPM}, {'science-gray': SPM}, @@ -206,7 +225,7 @@ targets_groups: list[dict[str, float]] = [ {'science-purple': SPM}, {'science-yellow': SPM}, ] -bus_resources = { +bus_base = { 'iron-plate', 'copper-plate', 'stone', @@ -214,42 +233,56 @@ bus_resources = { 'coal', 'steel', 'sulfur', - 'plastic', 'sulfuric-acid', + 'plastic', 'lubricant', } # TODO: science-blue is wrong print(f'{SPM=}') -print(f'{bus_resources=}') +print(f'{bus_base=}') bus_inputs = {} for targets in targets_groups: - results, intermediates = compute_base_resource_flow(targets, bus_resources) + reduced, intermediates = reduce_to_base_resources(targets, bus_base) print() print(f'{targets=}') print('intermediates') - for resource, count in sorted(intermediates.items()): - print(f' {resource:35}: {dot_align(tuple(intermediates.values()), count)}') - print('results') - for resource, count in sorted(results.items()): - print(f' {resource:35}: {dot_align(tuple(results.values()), count)}') + print_resource_group(intermediates) + print('reduced') + print_resource_group(reduced) - bus_inputs = add_recipe(bus_inputs, results, -1) + bus_inputs = add_recipe(bus_inputs, reduced, -1) +bus_inputs = drop_machines(bus_inputs) print() -print('final bus inputs') -for resource, count in sorted(bus_inputs.items()): - if resource.startswith(('assembler', 'chemical-plant', 'oil-refinery')): - continue - print(f' {resource:35}: {dot_align(tuple(bus_inputs.values()), count)}') +print('bus inputs') +print_resource_group(bus_inputs) # oil processing -oil_resources = { - 'sulfuric-acid', - 'light-oil', - 'heavy-oil', -} +oil_outputs = {k: v for k, v in bus_inputs.items() if k in {'sulfur', 'sulfuric-acid', 'plastic', 'lubricant'}} -oil_inputs = {} -# TODO compute +oil_base = {'petroleum-gas', 'light-oil', 'heavy-oil', 'water', 'iron-plate', 'coal'} + +print() +print('oil processing') +print() +print(f'{oil_outputs=}') +print(f'{oil_base=}') +oil_inputs, intermediates = reduce_to_base_resources(oil_outputs, oil_base) +print('intermediates') +print_resource_group(intermediates) +print('reduced') +print_resource_group(oil_inputs) + +oil_inputs = drop_machines(oil_inputs) +print() +print('oil inputs') +print_resource_group(oil_inputs) + +# oil refinery + + +# combine to compute mining requirements + +# mining