Сначала я скажу, как вы можете исправить свой код выше, затем я дам вам немного лучший способ кодировать это, если это то, что вы ищете.
Какчтобы исправить это
Ваша ошибка появляется, потому что ваш рекурсивный вызов _calc
отредактирует coins
, но не left
. Это связано с тем, что в функции _calc
left
был заменен локальной переменной.
Я добавил несколько динамических отступов «быстро и грязно», чтобы показать, как это работает:
def change_calc_2(cost, given): # input in full £xx.xx
coin_vals = [200, 100, 50, 20, 10, 5, 2, 1]
coins = [0] * len(coin_vals)
cost = cost * 100 # pence
given = given * 100
left = given - cost
def _calc(left,recur_level):
print("{}recursion level:".format(' '*4*recur_level), recur_level)
for i, c in enumerate(coin_vals):
print(" {}for loop level:".format(' '*4*recur_level), i)
print(" {}Amount left at start of kernel:".format(' '*4*recur_level), left)
print(" {}Coin val in question:".format(' '*4*recur_level), c)
if left == 0:
print("{}EXIT recursion level:".format(' '*4*recur_level), recur_level)
return coins # early exit routine
elif c > left:
continue
else:
coins[i] += 1
print(" {}coin added:".format(' '*4*recur_level), c)
left -= c
print(" {}Amount left at end of kernel:".format(' '*4*recur_level), left)
_calc(left,recur_level+1)
return coins
#_calc(left)
return _calc(left,0)
#return coins
Если мы быстро запустим это:
>>> change_calc_2(17,20)
recursion level: 0
for loop level: 0
Amount left at start of kernel: 300
Coin val in question: 200
coin added: 200
Amount left at end of kernel: 100 #<----- These values are the same
recursion level: 1
for loop level: 0
Amount left at start of kernel: 100
Coin val in question: 200
for loop level: 1
Amount left at start of kernel: 100
Coin val in question: 100
coin added: 100
Amount left at end of kernel: 0
recursion level: 2
for loop level: 0
Amount left at start of kernel: 0
Coin val in question: 200
EXIT recursion level: 2
for loop level: 2
Amount left at start of kernel: 0
Coin val in question: 50
EXIT recursion level: 1
for loop level: 1
Amount left at start of kernel: 100 #<----- These values are the same
Coin val in question: 100
coin added: 100
Amount left at end of kernel: 0
recursion level: 1
for loop level: 0
Amount left at start of kernel: 0
Coin val in question: 200
EXIT recursion level: 1
for loop level: 2
Amount left at start of kernel: 0
Coin val in question: 50
EXIT recursion level: 0
Ваша ошибка не позволяет корректно обновить left
. Если вы хотите использовать рекурсию, убедитесь, что вы просто правильно вложили свои вызовы:
def change_calc_rec(cost, given): # input in full £xx.xx
coin_vals = [200, 100, 50, 20, 10, 5, 2, 1]
coins = [0] * len(coin_vals)
cost = cost * 100 # pence
given = given * 100
left = given - cost
def _calc(left,coin_index):
i = coin_index
c = coin_vals[i]
print("{}coin_index:".format(' '*4*i), i)
while True:
if left == 0:
print("{}EXIT recursion level:".format(' '*4*i), i)
return coins # early exit routine
elif c > left:
break
else:
coins[i] += 1
print(" {}coin added:".format(' '*4*i), c)
left -= c
print(" {}Amount left at end of kernel:".format(' '*4*i), left)
if coin_index < len(coin_vals):
return _calc(left,coin_index+1)
else:
return coins
#_calc(left)
return _calc(left,0)
#return coins
Какой ваш уровень рекурсии должен совпадать с индексом монет. Раньше вы доходили до индекса, где ваша монета была больше требуемого изменения, затем запускали новый цикл с индексом 0. Выше это должно исправить.
Без рекурсии
Для этой проблемы рекурсия вообще не нужна. Вы можете кодировать его более безопасным способом, используя цикл while:
def change_calc(cost, given): # input in full £xx.xx
coin_vals = [200, 100, 50, 20, 10, 5, 2, 1]
coins = [0] * len(coin_vals)
cost = cost * 100 # pence
given = given * 100
left = given - cost
for i, c in enumerate(coin_vals):
while True:
if left == 0:
return coins # early exit routine
elif c > left:
break
else:
coins[i] += 1
left -= c
raise ValueError('Bad given or cost!')
Это будет продолжать цикл while
до тех пор, пока c > left
, , затем не перейдет на меньшие монеты. Возвращается, когда left == 0
. Возникает ошибка ValueError, если вы даете неверное значение стоимости или стоимости, например, left == 0
никогда не происходит.
Наслаждайтесь!