From 633999409c40a4d2d7e578eebce665a847e2efa4 Mon Sep 17 00:00:00 2001 From: Raphael Roberts Date: Sun, 2 Dec 2018 20:48:44 -0600 Subject: [PATCH] working prototype --- input | 9 +++ total_cost.py | 181 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 132 insertions(+), 58 deletions(-) create mode 100644 input diff --git a/input b/input new file mode 100644 index 0000000..3af0038 --- /dev/null +++ b/input @@ -0,0 +1,9 @@ +1 +bunch of screws +tiny silver nugget +end +1 +tiny iron nugget *2 +end +0 +0 diff --git a/total_cost.py b/total_cost.py index b9ec3a5..19fda7c 100644 --- a/total_cost.py +++ b/total_cost.py @@ -1,60 +1,125 @@ +import sys import re -compound = {} -base_comp = set() - -def get_input(comp): - ret = {} - ret['type'] = input('type: ').lower() - ret['parents'] = set() - if type == 'compound': - ret['sub'] = {} - first = True - while True: - i = input('sub: ' if first else '>').lower() - if i == 'end': - break - if i != '' - s = re.split(r' *\* ',i) - if len(s) == 2: - name,count = s +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: - name = s[0] - count = 0 - ret[name] = int(count) - first = False - return ret - -def get_sub(comp): - # either not base component or not entered yet - if comp not in base_comp: - try: - # check to see if it is already entered - subs = compound[comp] - except KeyError: - # entry - subs = get_input(comp) - - if subs['type'] == 'base': - base_comp.add(comp) - else: - compound[comp] = subs - return subs - - -def __inner__(comp,count,bases,components,prev = None): - component_data = get_sub(comp) - if prev: - component_data['parents'].add(prev) - # not a compound component - if component_data is None: - prev = bases.get(comp,0) - bases[comp] = prev + count - else: - prev = components.get(comp,0) - components[comp] = prev + count - for sub,count in component_data['sub']: - __inner__(sub,count,bases,components,comp) - -def get_overall_usage(comp): - ret_bases = {} - ret_components = {} + 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() \ No newline at end of file