麻省理工学院OCW 6.00的鸡肉麦块计划...再



我花了一点时间阅读了之前关于麻省理工学院开放式课程6.00题集的问题/答案,该题集涉及一个程序,用于确定6、9和20包鸡麦乐鸡的最大数量。不幸的是,我很难将这些答案集成到我自己尝试制作的代码中。

首先,这是我试图为其编写代码的问题集的实际措辞:

。。。我们可以写一个详尽的搜索,以找到无法准确数量购买的最大数量的麦乐鸡。搜索的格式可能应该遵循以下大纲:
•假设无法准确购买的麦乐鸡数量的可能实例,从1开始
?对于每个可能实例,称为n,测试是否存在非负整数a、b和c,以便6a+9b+20c=n。(这可以通过查看a、b和c的所有可行组合来完成)
•如果没有,n就不能准确购买,请保存n
·当你发现n的六个连续值实际上通过了具有精确解的测试时,保存的最后一个答案(而不是具有解的n的最后值)就是正确答案,因为你知道,根据这个定理,任何更大的数量也可以买到确切的数量。编写一个迭代程序,找出无法准确购买的最大数量的麦乐鸡。您的程序应按以下格式打印答案(提供正确的数字代替(n)):"无法准确购买的最大麦乐鸡数量:(n)">
提示:您的程序应该遵循上面的大纲

这是我的代码:

n = 1                                  #set first value for trying to solve the equation
savedn = []                            #list for holding values of n w/ no integer solution
consecutivecount = 0
while consecutivecount < 6:
for a in range(0,n):
for b in range(0,n):
for c in range(0,n):
if 6*a + 9*b + 20*c == n:
consecutivecount += 1
else:
#NOW A MIRACLE HAPPENS!!!
consecutivecount = 0      #resets consecutivecount value to zero
savedn += [n]             #adds current value of n to list
n += 1                        #increases value of n to continue test loop
print 'Largest amount of McNuggets that cannot be bought in exact quantity:',str(savedn[-1])+'.'

我的困难:

  1. 正如你所看到的,我被困在了这中间,在指示的地方。我看到这个问题的其他问题/答案使用bools,但我不确定为什么有人会这样做。我真的有使用bools吗?为什么?基本上,我希望能帮助找出一个有效的操作来执行"其他">

  2. 我不确定我是否真的正确使用了savedn列表。当我运行了这段代码的测试段时,我知道我显然是在向列表中添加值,但确认这是使用"savedn+=[n]"的正确方式会很好。

我仍然知道很少的命令,而且我的数学技能也很生疏,所以就像我在这门课上的最后一个问题一样,请假设我是个白痴。另一方面,如果我上面的尝试完全偏离了目标,请明确建议我应该如何从头开始。

感谢并为篇幅道歉——关于这个问题的其他讨论似乎不够彻底,没有用。(很抱歉这需要Python2.5。)

您就快到了。假设问题是"找到点什么来吃麦乐鸡的解决方案"?你有核心,可以用这样的东西来解决这个问题

solution = (0,0,0)
for a in range(0,n):
for b in range(0,n):
for c in range(0,n):
if 6*a + 9*b + 20*c == n:
solution = (a,b,c)

现在,你所需要做的就是像现在这样用簿记来围绕这个:

while consecutivecount < 6:
solution = (0,0,0)
# ** find a solution like above
if solution == (0,0,0):
consecutivecount = 0      #resets consecutivecount value to zero
savedn += [n]             #adds current value of n to list
else:
consecutivecount += 1
n += 1                        #increases value of n to continue test loop

因此,你为n寻找一个解决方案,如果你找到了一个,你就把连续计数加起来,如果你没有找到,你就省下另一个无法达到的数字(并重置连续计数)。在任何一种情况下,是时候继续进行另一个n了。

我使用了itertools.product来避免for循环的3个深度嵌套。这意味着我可以很容易地突破的循环

from itertools import product, count
v = [6,9,20]
min_v = min(v)
miss = 0
for n in count(1):
for w in product(range(n), repeat=len(v)):
if sum(i * j for i, j in zip(v, w)) == n:
break
else:
miss = n
if n == miss + min_v:
break
print miss

正如@Joran在对该问题的评论中注意到的那样,这确实测试了一堆不必要的案例。以下方法通过设置稍微不同的product来避免这些情况

from itertools import product, count
v = [6,9,20]
min_v = min(v)
miss = 0
for n in count(1):
for w in product(*(range(1 + n // i) for i in v)):
if sum(i * j for i, j in zip(v, w)) == n:
break
else:
miss = n
if n == miss + min_v:
break
print miss

如果我们使用阶跃参数进行测距,它可以进一步简化为这个

from itertools import product, count
v = [6,9,20]
min_v = min(v)
miss = 0
for n in count(1):
for w in product(*(range(0, n + 1, i) for i in v)):
if sum(w) == n:
break
else:
miss = n
if n == miss + min_v:
break
print miss

这里有一个通用版本,适用于任何数量的工件:

def solution_exists(amt, pieces, i=None):
"""
Return True if any whole multiples of pieces[:i+1] sum to amt, else False
"""
if i is None:
i = len(pieces) - 1   # start with last item
p = pieces[i]
if i:
return any(solution_exists(amt - p*k, pieces, i-1) for k in range(amt // p + 1))
else:
return amt % p == 0
def find_max_unbuyable(pieces):
least = min(pieces)
n = 0
last_unsolved = None
consecutive = 0
while consecutive < least:
n += 1
if solution_exists(n, pieces):
consecutive += 1
else:
last_unsolved = n
consecutive = 0
return last_unsolved
def main():
pieces = [6, 9, 20]
max_unbuyable = find_max_unbuyable(pieces)
print("Largest number of McNuggets that cannot be bought in exact quantity: {n}".format(n=max_unbuyable))
if __name__=="__main__":
main()

find_max_unbuyable是相当直接的;从问题的描述来看,这几乎是一步一步的。

CCD_ 5参与较多;它是一个递归可满足性测试。对于每个包,从最后一个开始,一直到第一个,它计算出可以购买的最大数量(amt // p)和剩余的购买数量(amt - p*k)。然后,它称自己反对减少的子问题。如果子问题已解决,那么问题也已解决,并且any缩短评估并返回True。对于基本情况(i == 0,我们正在查看最后一个包),当剩余量可被p(amt % p == 0)整除时,我们返回True。

以这种方式编写solution_exists有两个好处:首先,它是一个更有效的解决方案(尽可能少地迭代,将最后一块作为模除数而不是另一次迭代,一旦找到解决方案就短路);其次,因为它是递归的,所以它将很乐意对任意大量的包进行操作。

最新更新