我想编写一个程序,显示所有不同硬币(5c,10c,50c等)的组合可能达到一定值(例如$ 4)的所有方式。假设,对于初学者来说,我只想将50c,$ 1和2 $考虑为可能的组合。如果我想使用蛮力,我可以编写3个嵌套的while
循环,并在每次货币合计达到我想要的值(在本例中为$ 4)时返回该货币组合。但是,由于我们考虑了更多的货币选择(例如1c,5c,10c,25c,50c,$ 1,$ 2,$ 5,$ 10,$ 50,$ 100)和更大的金额(假设我希望所有组合都获得$ 400),代码变得非常冗长且难以维护。如果我想制定一种适用于任何国家和货币组合的通用算法,则不能依靠简单的循环嵌套。
鉴于此问题,我尝试使用装饰器,以便将循环嵌套在单个函数中:
INTENDED_SUM = 400
coin_count = {
200: 0,
100: 0,
50: 0,
}
def max_range(value):
return INTENDED_SUM / value
def coin_loop(coin_value):
def decorator(func):
while coin_count[coin_value] <= max_range(coin_value):
yield from func()
coin_count[coin_value] += 1
else:
coin_count[coin_value] = 0
return decorator
@coin_loop(100)
def get_combinations():
agg = sum([i * coin_count[i] for i in coin_count])
if agg == INTENDED_SUM:
yield coin_count
for i in get_combinations:
print(i)
这是输出:
{200: 0, 100: 4, 50: 0}
但是,如果我向get_combinations()
函数添加多个装饰器,则会引发TypeError:
@coin_loop(200)
@coin_loop(100)
@coin_loop(50)
def get_combinations():
agg = sum([i * coin_count[i] for i in coin_count])
if agg == INTENDED_SUM:
yield coin_count
Traceback (most recent call last):
File "31-coin_sums.py", line 29, in <module>
for i in get_combinations:
File "31-coin_sums.py", line 15, in decorator
yield from func()
TypeError: 'generator' object is not callable
所以我有两个问题:
为什么get_combinations已经显示为生成器,并且在代码的后两行中调用它时却不需要调用它?他们不应该这样吗?
for i in get_combinations():
print(i)
在这种情况下,为什么装饰器嵌套无效?预期输出应为:
{200: 2, 100: 0, 50: 0}
{200: 1, 100: 2, 50: 0}
{200: 1, 100: 1, 50: 2}
{200: 1, 100: 0, 50: 4}
{200: 0, 100: 4, 50: 0}
{200: 0, 100: 3, 50: 2}
{200: 0, 100: 2, 50: 4}
{200: 0, 100: 1, 50: 6}
{200: 0, 100: 0, 50: 8}
编辑:仅作为示例,我希望上面的代码(具有多个装饰器)与此等效,除了不嵌套whiles
:
INTENDED_SUM = 400
coin_count = {
200: 0,
100: 0,
50: 0,
}
def max_range(value):
return INTENDED_SUM / value
def get_combinations():
while coin_count[200] <= max_range(200):
while coin_count[100] <= max_range(100):
while coin_count[50] <= max_range(50):
agg = sum([i * coin_count[i] for i in coin_count])
if agg == INTENDED_SUM:
yield coin_count
coin_count[50] += 1
else:
coin_count[50] = 0
coin_count[100] += 1
else:
coin_count[100] = 0
coin_count[200] += 1
else:
coin_count[200] = 0
for i in get_combinations():
print(i)