Python make_change算法:计算精确变化的最佳方法
我刚开始学习Python,并练习使用来自伯克利CS课程的材料。这个问题来自那个班。如果有人能告诉我如何找到解决方案或帮助修复我的程序,我将非常感激 我遇到麻烦的功能是进行更改;它需要一个字典,每个键都是货币的值,值是您拥有的货币数量。该函数获取此字典和一个值,并返回根据给定字典构造的可能最短列表,该字典从最低到最高列出了与输入金额相加的货币单位。查看文档字符串以获得更具体的示例 当我在这个函数上运行doc测试时,doc测试给出的实际结果是大多数测试的正确顺序中的正确数字,但是许多测试在列表中都有列表,并且在足够的递归周期后,用于更改25的doc测试没有返回任何结果 有人能给我解释一下为什么这个程序一个也不给我,以及如何去掉列表中的列表吗?如果有任何帮助,我将不胜感激Python make_change算法:计算精确变化的最佳方法,python,dictionary,Python,Dictionary,我刚开始学习Python,并练习使用来自伯克利CS课程的材料。这个问题来自那个班。如果有人能告诉我如何找到解决方案或帮助修复我的程序,我将非常感激 我遇到麻烦的功能是进行更改;它需要一个字典,每个键都是货币的值,值是您拥有的货币数量。该函数获取此字典和一个值,并返回根据给定字典构造的可能最短列表,该字典从最低到最高列出了与输入金额相加的货币单位。查看文档字符串以获得更具体的示例 当我在这个函数上运行doc测试时,doc测试给出的实际结果是大多数测试的正确顺序中的正确数字,但是许多测试在列表中都有
def make_change(amount, coins):
"""Return a list of coins that sum to amount, preferring the smallest
coins available and placing the smallest coins first in the returned
list. The coins argument is a dictionary with keys that are positive
integer denominations and values that are positive integer coin counts.
>>> make_change(2, {2: 1})
[2]
>>> make_change(2, {1: 2, 2: 1})
[1, 1]
>>> make_change(4, {1: 2, 2: 1})
[1, 1, 2]
>>> make_change(4, {2: 1}) == None
True
>>> coins = {2: 2, 3: 2, 4: 3, 5: 1}
>>> make_change(4, coins)
[2, 2]
>>> make_change(8, coins)
[2, 2, 4]
>>> make_change(25, coins)
[2, 3, 3, 4, 4, 4, 5]
>>> coins[8] = 1
>>> make_change(25, coins)
[2, 2, 4, 4, 5, 8]
"""
if len(coins) == 0:
return None
smallest = min(coins)
rest = remove_one(coins, smallest)
lst = []
if smallest == amount:
return [smallest]
elif amount - smallest >= smallest:
amount -= smallest
lst.extend([smallest] + [make_change(amount, rest)])
return lst
elif amount - smallest < smallest:
return [make_change(amount, rest)]
def remove_one(coins, coin):
"""Remove one coin from a dictionary of coins. Return a new dictionary,
leaving the original dictionary coins unchanged.
>>> coins = {2: 5, 3: 2, 6: 1}
>>> remove_one(coins, 2) == {2: 4, 3: 2, 6: 1}
True
>>> remove_one(coins, 6) == {2: 5, 3: 2}
True
>>> coins == {2: 5, 3: 2, 6: 1} # Unchanged
True
"""
copy = dict(coins)
count = copy.pop(coin) - 1
if count:
copy[coin] = count
return copy
def兑换(金额、硬币):
“”“返回与金额相等的硬币列表,优先选择最小的。”
硬币可用,并将最小的硬币放在退回的硬币中的第一位
coins参数是一个带有正数键的字典
整数面额和正整数硬币计数的值。
>>>作出改变(2,{2:1})
[2]
>>>作出改变(2,{1:2,2:1})
[1, 1]
>>>作出改变(4,{1:2,2:1})
[1, 1, 2]
>>>make_change(4,{2:1})=无
真的
>>>硬币={2:2,3:2,4:3,5:1}
>>>找零钱(4枚硬币)
[2, 2]
>>>找零钱(8元,硬币)
[2, 2, 4]
>>>找零钱(25元,硬币)
[2, 3, 3, 4, 4, 4, 5]
>>>硬币[8]=1
>>>找零钱(25元,硬币)
[2, 2, 4, 4, 5, 8]
"""
如果len(硬币)==0:
一无所获
最小=最小(硬币)
剩余=移除一个(最小的硬币)
lst=[]
如果最小==金额:
返回[最小]
elif金额-最小值>=最小值:
金额-=最小值
第一次扩展([最小值]+[进行更改(金额,剩余)])
返回lst
elif金额-最小值<最小值:
返回[更改(金额、剩余)]
def移除一个(硬币、硬币):
“”“从硬币字典中取出一枚硬币。返回一本新字典,
保留原词典原样。
>>>硬币={2:5,3:2,6:1}
>>>移除一(硬币,2)={2:4,3:2,6:1}
真的
>>>移除一个(硬币,6)={2:5,3:2}
真的
>>>硬币=={2:5,3:2,6:1}不变
真的
"""
抄写(硬币)
计数=复制。弹出(硬币)-1
如果计算:
拷贝[硬币]=计数
返回副本
函数make\u change
返回列表或无
。这意味着两件事:(a)你不需要把它放在另一个列表中;(b)在将其返回值连接到其他列表之前,需要检查None
。如果我们将这些点应用到您的代码中,我们会得到如下结果:
change = make_change(amount, rest)
if change is None:
return None
else:
return [smallest] + change
更大的问题(为什么函数25次返回
None
)是由您的算法引起的:它是贪婪的(不管怎样消耗最小的硬币),因此如果它沿着一条不可能的路径前进,就会失败。您需要添加一些回溯逻辑。最直接的方法是使用递归。假设您必须使用列表中的硬币兑换100英镑[14,7,3,1]。
如果最短列表使用14枚硬币,则其长度将比使用相同硬币的最短方式更改86枚硬币的长度多1。如果它不使用14枚硬币,那么它将是使用[7,3,1]中的硬币兑换100枚硬币的最短方式。递归将为您解决回溯问题。这里的缩进似乎不正确,您能修复吗?您还可以演示如何最初调用
make\u change
?