-1
def solve(numLegs, numHeads):
    for numChicks in range(0, numHeads + 1):
        numPigs = numHeads - numChicks
        totLegs = 4*numPigs + 2*numChicks
        if totLegs == numLegs:
            return [numPigs, numChicks]
    return [None, None]

def barnYard(heads, legs):
    pigs, chickens = solve(legs, heads)
    if pigs == None:
        print "There is no solution."
    else:
        print 'Number of pigs: ', pigs
        print 'Number of Chickens: ', chickens

我正在学习 Python 并遇到了这个例子,有人可以用简单的英语(或伪代码)逐行解释它在做什么。

非常感谢

4

5 回答 5

8

solve正在计算需要多少只小鸡(1 头,2 条腿)和多少头猪(1 头,4 条腿)才能达到给定的头和腿数量。

它使用“蛮力”,即最简单的方法:

  • 它会尝试甚至可能的小鸡数量,从根本没有到指定的正面数量(这是循环的作用for numChicks in range(0, numHeads + 1):,因为range给出了从包含的起始值到排除的结束值的整数);
  • 对于每个给定numChicks,它通过语句计算将有多少头猪来提供所要求的头数numPigs = numHeads - numChicks
  • 然后它计算这些小鸡和猪总共有多少条腿,由 totLegs = 4*numPigs + 2*numChicks
  • 然后它检查是否totLegs等于请求的数字:如果是,它返回一个包含两项的列表,即解决问题的小鸡和猪的数量
  • 最后,如果它在没有返回值的情况下“落到for循环的底部”,它就知道没有解决方案,并通过返回一个列表来表示这一点,每个列表的两个项目都是None.

barnYard只需将解决方案委托给solve,并以一种易于阅读的方式将其打印出来,可以是“无解决方案”,也可以是装饰精美的小鸡和猪的数量。

现在,为了继续进步,问问自己是否solve可以更有效地编写。显然,如果腿的数量少于正面数量的两倍,或者超过正面数量的四倍,或者奇数 - 也许solve可以测试这些情况并[None, None]立即返回。你能写代码吗...?

这可能并不明显,但是头和腿数量的所有其他组合都有一个解决方案——并且有一种方法可以通过算术找到它,而不需要循环。想一想,或许借助初中代数……

于 2009-10-11T04:22:24.340 回答
2

Alex Martelli 提到了一个代数解决方案,为了完整起见,我将在此处包含该解决方案。它可以通过使用联立方程来解决。作为一个简单的数学解决方案,它可能更快,至少对于大量的腿和头来说:-)

让:

  • H是正面的数量;
  • L是腿的数量;
  • C是小鸡的数量;和
  • P是猪的数量。

给定CP,我们可以计算其他两个变量:

H =  C +  P (1)
L = 2C + 4P (2)

我将在下面详细说明计算中的一步。毫无疑问,数学倾向可以指出可以组合步骤,但我更愿意明确。从(1),我们可以计算:

   H = C + P
=> 0 = C + P - H       [subtract H from both sides]
=> 0 = H - C - P       [multiply both sides by -1]
=> P = H - C           [add P to both sides] (3)

并将其代入(2):

    L = 2C + 4P
=>  L = 2C + 4(H - C)   [substitute H-C for P]
=>  L = 2C + 4H - 4C    [expand 4(H-C) to 4H-4C]
=>  L = 4H - 2C         [combine 2C-4C into -2C]
=>  0 = 4H - 2C - L     [subtract L from both sides]
=> 2C = 4H - L          [add 2C to both sides]
=>  C = 2H - L/2        [divide both sides by 2] (4)

现在你有两个公式,一个可以从头和腿计算小鸡的数量(4),另一个可以从小鸡和头计算猪的数量(3)

所以这是执行此操作的 Python 代码,通过适当的检查以确保您不允许一些更奇怪的数学解决方案,例如 2 个头和 7 条腿给我们一头半猪和半只小鸡,或者 1 个头和12 条腿给 5 头猪和 -4 只小鸡 :-)

def solve (numLegs, numHeads):
    # Use the formulae (these make integers).
    chicks = numHeads * 2 - int (numLegs / 2)
    pigs = numHeads - chicks

    # Don't allow negative number of animals.
    if chicks < 0 or pigs < 0:
        return [None, None]

    # Don't allow fractional animals.
    if chicks * 2 + pigs * 4 != numLegs:
        return [None, None]
    if chicks + pigs != numHeads:
        return [None, None]

    return [pigs, chicks]

当然,如果您传入小数的头或腿,则所有赌注都将被取消。这是一个完整的测试程序,因此您可以尝试各种值以确保两种方法返回相同的值:

import sys

def usage (reason):
    print "Error: %s"%(reason)
    print "Usage: solve <numHeads> <numLegs>"
    sys.exit (1);

def solve1 (numLegs, numHeads):
    for numChicks in range (0, numHeads + 1):
        numPigs = numHeads - numChicks
        totLegs = 4 * numPigs + 2 * numChicks
        if totLegs == numLegs:
            return [numPigs, numChicks]
    return [None, None]

def solve2 (numLegs, numHeads):
    chicks = numHeads * 2 - int (numLegs / 2)
    pigs = numHeads - chicks
    if chicks < 0 or pigs < 0:           return [None, None]
    if chicks * 2 + pigs * 4 != numLegs: return [None, None]
    if chicks + pigs != numHeads:        return [None, None]
    return [pigs, chicks]

if len (sys.argv) != 3:
    usage ("Wrong number of parameters (%d)"%(len (sys.argv)))

try:    heads = int (sys.argv[1])
except: usage ("Invalid <numHeads> of '%s'"%(sys.argv[1]))

try:    legs = int (sys.argv[2])
except: usage ("Invalid <numLegs> of '%s'"%(sys.argv[2]))

print "[pigs, chicks]:"
print "  ", solve1 (legs, heads)
print "  ", solve2 (legs, heads)
于 2009-10-12T03:06:12.837 回答
1

它遍历猪和鸡的所有可能组合(具有指定的头数),直到找到具有正确腿数的组合,然后返回猪和鸡的数量。如果它通过每个组合而没有找到有效的答案,则返回 [None, None] 以指示失败。

于 2009-10-11T04:15:14.120 回答
1

本质上,solve是遍历鸡和猪的所有可能组合,当找到匹配项时,将其返回。)

NumChickens + NumPigs 必须等于 NumHeads,因此它检查从 0 到 NumHeads 的每个 NumChickens(就是这样for range(0,NumHeads+1)做的),并将 NumPigs 设置为 NumHeads-NumChickens。

从那里开始,只需乘以英尺数,看看它们是否匹配。

于 2009-10-11T04:19:38.293 回答
1

基本上,它试图找出问题的答案,“如果农场里有 X 头和 Y 腿,那么农场里有多少鸡和猪?” 该for numChicks in range(0, numHeads + 1):代码创建了一个变量 numChicks,并从 numChicks = 0 循环到 numChicks = numHeads。(注意:范围函数不包括最大值)。

对于每个数量的 numChicks,它会检查 numChicks 和相应的 numPigs 值是否得出正确的 numLegs 值。numHeads 总是正确的,因为 numChicks + numPigs = numHeads,但 numLegs 会根据分布而变化——因此是循环。如果在任何时候找到了解决方案(当 totLegs == numLegs 时),则返回该值。如果整个循环完成并且没有找到解决方案,则返回列表 [None, None],这意味着该输入没有解决方案。

于 2009-10-11T04:22:45.040 回答