我有10个,20个,50个音符,当我需要支付任何金额时,我需要找到最佳组合。因此对于例如当我需要支付7时,我将支付5和2的注释
我有一个计算这个的函数。但我需要运行相同的功能3或4次,如下所示。如何递归调用函数?
my_dir={}
import bisect
def my_change(my_amount):
c=[1,2,5,10,20,50,100,500]
my_pos=bisect.bisect(c, my_amount)
my_val=c[my_pos-1]
my_num=my_amount//my_val
my_recurr=my_amount-(my_num*c[my_pos-1])
my_dir[my_val] = my_num
return my_recurr
有没有更好的方法来计算这个?
my_change(417)
17
my_change(17)
7
my_change(7)
2
my_change(2)
0
my_dir
{2: 1, 5: 1, 10: 1, 100: 4}
更新
根据可用的内容,组合可能会发生变化!
available_cash={1:20, 2:10, 10:100, 50:100, 100:1, 500:1}
应该导致:
actual_pay={1:1, 2: 3, 10: 1, 50:6, 100: 1}
更新
有没有更好的方法对此进行编码?
amt=417
my_dict={}
available_cash={1:20, 2:10, 10:100, 50:100, 100:1, 500:1}
new_list=sorted(available_cash, reverse=True)
for key in new_list:
if amt >= key * available_cash[key]:
my_dict[key] = available_cash[key]
amt = amt - (key * available_cash[key])
else:
if amt >= key:
notes = amt // key
amt = amt - (key * notes)
my_dict[key] = notes
更新1:
如果我需要在付款后找到自动柜员机中的留言,我可以使用计数器
from collections import Counter
A = Counter(available_cash)
B = Counter(my_dict)
A - B
Counter({10: 99, 50: 94, 1: 19, 2: 7, 500: 1})
答案 0 :(得分:3)
你甚至不需要使用递归,你可以在一段时间内换行,所以它会一直计算直到变化为0,基本上是你手动做的事情,但只有1次运行:< / p>
my_dir={}
import bisect
def my_change(my_amount):
my_dict={}
c=[1,2,5,10,20,50,100,500]
while (my_amount > 0 ):
my_pos=bisect.bisect(c, my_amount)
my_val=c[my_pos-1]
my_num=my_amount//my_val
my_recurr=my_amount-(my_num*c[my_pos-1])
my_dir[my_val] = my_num
my_amount = my_recurr
return my_dir
答案 1 :(得分:0)
您可以使用以下内容:
my_dir = {}
change = 417
def my_change(my_amount):
# Your function code here
while change > 0:
change = my_change(change)
但实际上,您的代码可以简化,带递归的解决方案是:
def my_change(amount, i=None):
c = [1, 2, 5, 10, 20, 50, 100, 500]
if i is None:
i = len(c) - 1
note = c[i]
n, rest = divmod(amount, note)
result = {}
if n > 0:
result[note] = n
if rest > 0:
result.update(my_change(rest, i - 1))
return result
无需bisect
或复杂的计算。
答案 2 :(得分:0)
如果你坚持以递归的方式做这件事,你可以使用一个小帮手函数来调用自己,这个函数会以不断减少的量调用自身(直到它达到零),然后传递给目前使用的一组音符。像
import collections
notes = [500, 100, 50, 20, 10, 5, 2, 1]
def my_change(amount):
def go(amount, notesUsed):
if amount <= 0:
return notesUsed
largestNote = next(x for x in notes if x <= amount)
notesUsed[largestNote] += 1
return go(amount - largestNote, notesUsed)
return go(amount, collections.defaultdict(int))
go
是执行实际递归的本地帮助函数,defaultdict
用于计算笔记。
答案 3 :(得分:0)
Python不鼓励递归。 Python无法优化tail-call递归,并且它限制了递归调用的最大深度(尽管可以修改该限制)。这个特定的应用程序不会深度递归,但最好避免Python中的递归,除非它适合于问题,例如走树结构。
这个问题很容易通过迭代来解决,使用greedy algorithm(如何适用于与钱连接的任务:))。在每个阶段,只需删除小于当前数量的最高音符的倍数。
例如:
#!/usr/bin/env python
all_notes = [1, 2, 5, 10, 20, 50, 100, 500]
def my_change(amount):
my_notes = list(all_notes)
change = {}
print amount
while amount > 0:
while my_notes[-1] > amount:
my_notes.pop()
note = my_notes[-1]
num, amount = divmod(amount, note)
print '%d x %d = %d, %d' % (num, note, num * note, amount)
change[note] = num
return change
print my_change(9)
print my_change(26)
print my_change(873)
<强>输出强>
9
1 x 5 = 5, 4
2 x 2 = 4, 0
{2: 2, 5: 1}
26
1 x 20 = 20, 6
1 x 5 = 5, 1
1 x 1 = 1, 0
{1: 1, 20: 1, 5: 1}
873
1 x 500 = 500, 373
3 x 100 = 300, 73
1 x 50 = 50, 23
1 x 20 = 20, 3
1 x 2 = 2, 1
1 x 1 = 1, 0
{1: 1, 2: 1, 100: 3, 50: 1, 500: 1, 20: 1}
我在函数中添加了一些print
语句,以便您可以关注正在发生的事情。
my_change()
函数的核心是内置divmod()
函数,它执行除法,将商和余数作为元组返回。 my_change()
也使用list.pop()
方法删除my_notes
过大的注释,all_notes
是my_notes
列表的临时副本。
修改此函数以将bisect
作为参数很容易,因此如果因某些原因无法获得完整的注释,则可以使用它。
答案 4 :(得分:0)
所以,既然你已经编辑了这个问题,我们就有了新的要求
我要提出的代码比你的代码要长一些,但是考虑到你实际上也应该修改available_cash
,因为你是从ATM取钱的。很明显,取款会使机器中可用的纸币数量减少。
from collections import OrderedDict
amount = 417
available_cash = OrderedDict((
(1, 20), (2, 10), (10, 100), (50, 100), (100, 1), (500, 1)
))
def my_change(amount, available_cash):
change = {}
for note in reversed(available_cash.keys()):
note_count = amount / note
if note_count == 0:
continue
elif note_count > available_cash[note]:
note_count = available_cash[note]
available_cash[note] = 0
else:
available_cash[note] -= note_count
change[note] = note_count
amount -= note_count * note
if amount == 0:
break
return change
print my_change(amount, available_cash)
我也放弃了递归函数调用的想法
stdlib
中另一个重要的事情是OrderedDict
类。