Try this with your list of resources.
The format of resources I choose is a dict as it is easier to process, but other formats can be converted tell me if you have. Example.
# Input resources data
resources1 = {
'itema1':10, 'itema6': 5,
'itemb2': 2,
'itemc2': 1
}
resources2 = {
'itema1':6, 'itema2': 2, 'itema3': 5, 'itema6': 5,
'itemb1': 2,'itemb2': 2, 'itemb3': 2,
'itemc1': 1, 'itemc2': 2
}
resources3 = {
'itema1':10, 'itema2': 4, 'itema3': 5, 'itema4': 2, 'itema5': 5, 'itema6': 3,
'itemb1': 2,'itemb2': 4, 'itemb3': 2, 'itemb4': 2, 'itemb5': 2,
'itemc1': 1, 'itemc2': 3, 'itemc3': 2
}
In the main(), we will read this input and convert to a list then process it.
def main():
# Add resources into a list
myresources = []
myresources.append(resources1)
myresources.append(resources2)
myresources.append(resources3)
# Loop on each resource from the myresources.
for i, r in enumerate(myresources):
r = build_missing_items(r)
max_level, resources_remaining = level_progress(r)
# Print summary of the given resources r
print(f'Input resources # {i+1}')
print(f'max level : {max_level}')
print(f'resources remaining : {get_dict_with_value(resources_remaining)}')
print(f'resources original : {get_dict_with_value(r)}')
print()
The build_missing_items() is just a function that takes a resource and supply missing items but with value zero.
def build_missing_items(res):
"""Read resources res and if there are missing items add
the item with zero value. This useful when we create items
as we progress in levels.
Example:
if itema7 is missing, just add {"itema7: 0}
"""
...
The level_progress() here it checks the resource in every levels.
def level_progress(r):
"""Returns max level reached and the remaining resources info"""
max_level_reach = 1
res = r.copy()
status, res = level1(res) # Create/subract resources at this level
if status: # if True it can advance to level 2
max_level_reach += 1
if status:
status, res = level2(res)
if status:
max_level_reach += 1
if status:
status, res = level3(res)
if status:
max_level_reach += 1
...
There are 8 level functions level1(res), level2(res) ... In these levels we check from available resources if we can create an item for next level with the application of the rules. I maximize the creation of items for next level see the comments in the code below. So the idea is to create an item for next level and then subtract what was used in the creation. If we succeed in creating an item for the next level we set the status to True meaning we can advance to next level. We return this status along the updated resources for the next level check. level checking starts at level1, level2 ... level8.
def level1(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema1', 0) # Get the count of itema1
itemb = par.get('itemb1', 0)
itemc = par.get('itemc1', 0)
ok = 0 # if ok is 1 then we can go to the next level or level 2
if itema >= 3:
par['itema2'] += itema // 3 # maximize conversion, if there are 6 itema1 then we will create 6/3 or 2 itema2
par['itema1'] -= 3 * (itema // 3) # reduce the original value
ok += 1
if itemb >= 3:
par['itemb2'] += itemb // 3
par['itemb1'] -= 3 * (itemb // 3)
ok += 1
if itemc >= 3:
par['itemc2'] += itemc // 3
par['itemc1'] -= 3 * (itemc // 3)
ok += 1
status = True if ok else False
return status, par
Output
With those 3 resources at the top, this is the result.
Intepretation in resources #1 result.
It reaches level 3. itema1 starts at 10 but now it is only 1 because we created 3 itema2 which consumes 9 itema1. 10-9 is 1 that 1 is the remaining itema1 count. At level 2, we need a2, b2 and c2 to advance to level 3. We have a2, we have b2 and we also have c2 that is why we reached level 3. But we cannot advance to level 4 because it requires at least 2 a3 or 2 b3 or 2 c3 and we cannot satisfy that conditions see the resources remaining we only have 1 a3.
Input resources # 1
max level : 3
resources remaining : {'itema1': 1, 'itema6': 5, 'itemb2': 1, 'itema2': 2, 'itema3': 1}
resources original : {'itema1': 10, 'itema6': 5, 'itemb2': 2, 'itemc2': 1}
Input resources # 2
max level : 4
resources remaining : {'itema2': 2, 'itema3': 1, 'itema6': 5, 'itemb1': 2, 'itemc1': 1, 'itema4': 3, 'itemb4': 1}
resources original : {'itema1': 6, 'itema2': 2, 'itema3': 5, 'itema6': 5, 'itemb1': 2, 'itemb2': 2, 'itemb3': 2, 'itemc1': 1, 'itemc2': 2}
Input resources # 3
max level : 6
resources remaining : {'itema1': 1, 'itema2': 4, 'itema4': 5, 'itema6': 6, 'itemb1': 2, 'itemb2': 1, 'itemb4': 2, 'itemc1': 1, 'itemb6': 1}
resources original : {'itema1': 10, 'itema2': 4, 'itema3': 5, 'itema4': 2, 'itema5': 5, 'itema6': 3, 'itemb1': 2, 'itemb2': 4, 'itemb3': 2, 'itemb4': 2, 'itemb5': 2, 'itemc1': 1, 'itemc2': 3, 'itemc3': 2}
Full code
def level8(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema8', 0)
itemb = par.get('itemb8', 0)
itemc = par.get('itemc8', 0)
# Maximize creations.
ok = 0
while True:
if itema and itemb and itemc:
ok += 1
par['itema9'] += 1 # create item for next level
par['itema8'] -= 1 # reduce item on current level
par['itemb8'] -= 1
par['itemc8'] -= 1
itema -= 1
itemb -= 1
itemc -= 1
else:
break
status = True if ok else False
return status, par
def level7(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema7', 0)
itemb = par.get('itemb7', 0)
itemc = par.get('itemc7', 0)
ok = 0
if itema >= 3:
par['itema8'] += itema // 3 # maximize conversion
par['itema7'] -= 3 * (itema // 3) # reduce the original value
ok += 1
if itemb >= 3:
par['itemb8'] += itemb // 3
par['itemb7'] -= 3 * (itemb // 3)
ok += 1
if itemc >= 3:
par['itemc8'] += itemc // 3
par['itemc7'] -= 3 * (itemc // 3)
ok += 1
status = True if ok else False
return status, par
def level6(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema6', 0)
itemb = par.get('itemb6', 0)
itemc = par.get('itemc6', 0)
# Maximize creations.
ok = 0
while True:
if itema and itemb and itemc:
ok += 1
par['itema7'] += 1 # create item for next level
par['itema6'] -= 1 # reduce item on current level
par['itemb6'] -= 1
par['itemc6'] -= 1
itema -= 1
itemb -= 1
itemc -= 1
else:
break
status = True if ok else False
return status, par
def level5(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema5', 0)
itemb = par.get('itemb5', 0)
itemc = par.get('itemc5', 0)
ok = 0
if itema >= 2:
par['itema6'] += itema // 2 # maximize conversion
par['itema5'] -= 2 * (itema // 2) # reduce the original value
ok += 1
if itemb >= 2:
par['itemb6'] += itemb // 2
par['itemb5'] -= 2 * (itemb // 2)
ok += 1
if itemc >= 2:
par['itemc6'] += itemc // 2
par['itemc5'] -= 2 * (itemc // 2)
ok += 1
status = True if ok else False
return status, par
def level4(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema4', 0)
itemb = par.get('itemb4', 0)
itemc = par.get('itemc4', 0)
# Maximize creations.
ok = 0
while True:
if itema and itemb and itemc:
ok += 1
par['itema5'] += 1 # create item for next level
par['itema4'] -= 1 # reduce item on current level
par['itemb4'] -= 1
par['itemc4'] -= 1
itema -= 1
itemb -= 1
itemc -= 1
else:
break
status = True if ok else False
return status, par
def level3(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema3', 0)
itemb = par.get('itemb3', 0)
itemc = par.get('itemc3', 0)
ok = 0
if itema >= 2:
par['itema4'] += itema // 2 # maximize conversion
par['itema3'] -= 2 * (itema // 2) # reduce the original value
ok += 1
if itemb >= 2:
par['itemb4'] += itemb // 2
par['itemb3'] -= 2 * (itemb // 2)
ok += 1
if itemc >= 2:
par['itemc4'] += itemc // 2
par['itemc3'] -= 2 * (itemc // 2)
ok += 1
status = True if ok else False
return status, par
def level2(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema2', 0)
itemb = par.get('itemb2', 0)
itemc = par.get('itemc2', 0)
# Maximize creations.
ok = 0
while True:
if itema and itemb and itemc:
ok += 1
par['itema3'] += 1 # create item for next level
par['itema2'] -= 1 # reduce item on current level
par['itemb2'] -= 1
par['itemc2'] -= 1
itema -= 1
itemb -= 1
itemc -= 1
else:
break
status = True if ok else False
return status, par
def level1(par):
"""Create resources for next level from the given initial resources par"""
status = False
itema = par.get('itema1', 0) # Get the count of itema1
itemb = par.get('itemb1', 0)
itemc = par.get('itemc1', 0)
ok = 0 # if ok is 1 then we can go to the next level or level 2
if itema >= 3:
par['itema2'] += itema // 3 # maximize conversion, if there are 6 itema1 then we will create 6/3 or 2 itema2
par['itema1'] -= 3 * (itema // 3) # reduce the original value
ok += 1
if itemb >= 3:
par['itemb2'] += itemb // 3
par['itemb1'] -= 3 * (itemb // 3)
ok += 1
if itemc >= 3:
par['itemc2'] += itemc // 3
par['itemc1'] -= 3 * (itemc // 3)
ok += 1
status = True if ok else False
return status, par
def get_dict_with_value(res):
"""Convert res into a new dict that has values"""
ret = {}
for k, v in res.items():
if v == 0:
continue
ret.update({k: v})
return ret
def level_progress(r):
"""Returns max level reached and the remaining resources info"""
max_level_reach = 1
res = r.copy()
status, res = level1(res) # Create/subract resources at this level
if status: # if True it can advance to level 2
max_level_reach += 1
if status:
status, res = level2(res)
if status:
max_level_reach += 1
if status:
status, res = level3(res)
if status:
max_level_reach += 1
if status:
status, res = level4(res)
if status:
max_level_reach += 1
if status:
status, res = level5(res)
if status:
max_level_reach += 1
if status:
status, res = level6(res)
if status:
max_level_reach += 1
if status:
status, res = level7(res)
if status:
max_level_reach += 1
if status:
status, res = level8(res)
if status:
max_level_reach += 1
return max_level_reach, res
def build_missing_items(res):
"""Read resources res and if there are missing items add
the item with zero value. This useful when we create items
as we progress in levels.
Example:
if itema7 is missing, just add {"itema7: 0}
"""
for c in ['a', 'b', 'c']:
for i in range(1, 10):
found = False
itm = f'item{c}{i}'
for k, v in res.items():
if itm == k:
found = True
break
if not found: # add
res.update({itm: 0})
return res
# Input resources data
resources1 = {
'itema1':10, 'itema6': 5,
'itemb2': 2,
'itemc2': 1
}
resources2 = {
'itema1':6, 'itema2': 2, 'itema3': 5, 'itema6': 5,
'itemb1': 2,'itemb2': 2, 'itemb3': 2,
'itemc1': 1, 'itemc2': 2
}
resources3 = {
'itema1':10, 'itema2': 4, 'itema3': 5, 'itema4': 2, 'itema5': 5, 'itema6': 3,
'itemb1': 2,'itemb2': 4, 'itemb3': 2, 'itemb4': 2, 'itemb5': 2,
'itemc1': 1, 'itemc2': 3, 'itemc3': 2
}
def main():
# Add resources into a list
myresources = []
myresources.append(resources1)
myresources.append(resources2)
myresources.append(resources3)
# Loop on each resource from the myresources.
for i, r in enumerate(myresources):
r = build_missing_items(r)
max_level, resources_remaining = level_progress(r)
# Print summary of the given resources r
print(f'Input resources # {i+1}')
print(f'max level : {max_level}')
print(f'resources remaining : {get_dict_with_value(resources_remaining)}')
print(f'resources original : {get_dict_with_value(r)}')
print()
# Test
main()