2

我进行了快速搜索,但找不到任何对我的问题有帮助的东西。

我正在尝试制作一个程序,该程序采用前 5 个数字并获取他们的产品,如果该产品是迄今为止发现的最大的产品,那么它就是这样设置的。

我的代码是:

string = str(integer)

x = 0
largest = 0
stringlength = len(string)

while x < stringlength:
    a = int(string[x])
    b = int(string[x+1])
    c = int(string[x+2])
    d = int(string[x+3])
    e = int(string[x+4])
    if (a*b*c*d*e > largest):
        largest = a*b*c*d*e
        print(largest)
    x += 1

print(largest)

我排除了整数值本身,但作为参考,它的长度为 1000 位。每当我尝试运行此代码时,我都会收到“IndexError:字符串索引超出范围”。任何人都可以帮忙吗?

4

2 回答 2

7
string = str(integer)

x = 0
largest = 0
stringlength = len(string)

while x < stringlength-4: # going to -5 would be out of rangue
    a = int(string[x])
    b = int(string[x+1])
    c = int(string[x+2])
    d = int(string[x+3])
    e = int(string[x+4])
    if (a*b*c*d*e > largest):
        largest = a*b*c*d*e
        print(largest)
    x += 1

print(largest)
于 2013-06-18T22:04:29.963 回答
2

这是一个典型的off-by-one 错误(或者,在这种情况下,off-by-4 错误)。

x到达时stringlength-4x+4stringlength,即过去的结束string。所以,你需要x < stringlength-4,不是x < stringlength

但是您可能需要考虑重写代码以使用更高级别的抽象,以使这些问题更难遇到并且更容易思考。


首先,而不是这个:

x= 0
while x < stringlength:
    # ...
    x += 1

只需这样做:

for x in range(stringlength):

然后你可以用这个解决你的问题:

for x in range(stringlength-4):

但让我们更进一步。


如果你对字符串进行切片,你将不会得到IndexError

for x in range(len(stringlength)):
    a, b, c, d, e = map(int, string[x:x+4])

但是,现在您将ValueError在拆包中得到一个。但实际上,您无需在此处解压缩为 5 个单独的变量。只需保持序列并将其相乘即可。(你可以用循环来做到这一点,但在我看来,这是少数几个reduce用 Python 编写东西的最易读的方式之一。)

for x in range(len(stringlength)):
    values = map(int, string[x:x+4])
    prod = reduce(operator.mul, values)
    if prod > largest:
        largest = prod
        print(largest)

现在不再有错误了——但那是因为您将最后的 4、3、2 和 1 数字相乘。这正是问题所在:您从未决定过那里应该发生什么。

所以,现在,你可以做出明确的决定。您想将它们计为批次,还是跳过它们?

如果您想进一步向前推进,您可以使用 编写滑动窗口分组器函数itertools,一个版本的行为类似于zip(当窗口的右边缘超出列表末尾时zip_longest停止),另一个版本的行为类似于(仅当窗口的边缘熄灭):

def groupwise(iterable, n):
    groups = itertools.tee(iterable, n)
    for i, group in enumerate(groups):
        next(itertools.islice(group, i, i), None)
    return zip(*groups)

def groupwise_longest(iterable, n, fillvalue=None):
    groups = itertools.tee(iterable, n)
    for i, group in enumerate(groups):
        next(itertools.islice(group, i, i), None)
    return itertools.zip_longest(*groups, fillvalue=fillvalue)

现在,您可以这样做:

for group_of_five in groupwise_longest(string, 5, 1):
    values = map(int, group)
    prod = reduce(operator.mul, values)
    if prod > largest:
        largest = prod
        print(largest)

然后,如果您决定最后不比较不完整的组,只需将第一行更改为:

for group_of_five in groupwise(string, 5):

然后您可以将所有工作移到for循环之外:

groups = groupwise_longest(string, 5, 1)
intgroups = (map(int, group) for group in groups)
prods = (reduce(operator.mul, group) for group in groups)

现在我们有了一系列产品,很明显要找到最高的产品,那就是:

print(max(prods))

例如:

>>> string = '12345678987654321'
>>> groups = groupwise(string, 5)
>>> intgroups = (map(int, group) for group in groups)
>>> prods = (reduce(operator.mul, group) for group in groups)
>>> max(prods)
28224

请注意,您无处可犯一个错误或任何其他“小”错误。当然,你仍然可能得到完全错误的东西,或者只是不知道如何编写它,但至少你的错误将是明显的大错误,更容易调试。

于 2013-06-18T22:17:33.470 回答