import sys import re ITEMS = {} ################################################################################################################################ # file operations # # this section is dedicated to operations that save, load, and parse data stored to disk # # || || || || || || || || || || || # # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ # ################################################################################################################################ ################################################################################################################################ # user input # # this section is dedicated to operations that will not have any other purpose other than collecting data # # || || || || || || || || || || || # # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ # ################################################################################################################################ class user_input: def __init__(self,comp_name): valid = ('raw','compound') error = True while not error: try: type = int(input("~{}~\ntype (0. {} | 1. {}): ".format(comp_name,*valid))) error = False except ValueError: pass self.type = valid[type] if self.type == 'compound': self.subs = {} i = 1 while True: inp = input('sub #{} ({{comp_name}} * {{count}}): '.format(i)) if inp == 'end': break sr = re.split(r' *\* *',inp) name = sr[0] if len(sr) == 1: count = 1 else: count = int(sr[1]) self.subs[name] = count i += 1 def recursive_fill_in(comp_name): global ITEMS if not comp_name in ITEMS.keys(): res = user_input(comp_name) if res.type == 'raw': ITEMS[comp_name] = raw_material(comp_name) else: ITEMS[comp_name] = complex_item(comp_name,res.subs) for sub in res.subs.keys(): recursive_fill_in(sub) ################################################################################################################################ # complexity # # this section is dedicated to operations that involve all processing and understanding of the input data # # || || || || || || || || || || || # # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ # ################################################################################################################################ class item: def __init__(self,name): self.name = name global ITEMS ITEMS[name] = self class raw_material(item): def __init__(self,name): super().__init__(name) self.complexity = 0 class complex_item(item): def __init__(self,name,sub_components): super().__init__(name) self.sub_components = sub_components self.naive_complexity = True self.all_sub = set(self.sub_components.keys()) def recalculate_total_completixy(self): for name in self.sub_components.keys(): component = ITEMS[name] if isinstance(component,complex_item): if component.naive_complexity: component.recalculate_total_completixy() component.naive_complexity = False self.all_sub.update(component.all_sub) @property def complexity(self): if self.naive_complexity: self.recalculate_total_completixy() self.naive_complexity = False return len(self.all_sub) def get_raw_material_cost(self,ret = {}): for name,count in self.sub_components.items(): component = ITEMS[name] if isinstance(component,raw_material): prev = ret.get(name,0) ret[name] = prev + count elif isinstance(component,complex_item): component.get_raw_material_cost(ret) return ret def get_component_cost(self,ret = {}): for name,count in self.sub_components.items(): component = ITEMS[name] if isinstance(component,complex_item): prev = ret.get(name,0) ret[name] = prev + count component.get_component_cost(ret) return ret def get_build_info(self): component_view = self.get_raw_material_cost() material_view = self.get_component_cost() build_order = component_view.items() build_order = sorted(build_order,key = lambda item: ITEMS[item[0]].complexity) return material_view,build_order def main(): name = sys.argv[1] recursive_fill_in(name) print(ITEMS[name].get_build_info()) if __name__ == "__main__": main()