Python 嵌套的循环输出不可预测?



我有以下代码,这是我为项目欧拉问题#4编写的:

回文数的两种读法相同。由两个 2 位数字的乘积构成的最大回文是 9009 = 91 × 99。

找到由两个 3 位数字的乘积制成的最大回文。

def foo():
for x in xrange (999,100,-1):
for y in xrange (999,100,-1):
product= (x*y)
if str(product)== str(product)[::-1]:
print product
foo()

这段代码生成所有回文的连续输出,因为我省略了一个中断。但是,输出如下所示:

580085
514415
906609
119911
282282
141141
853358
650056
601106
..
..

我不知道为什么最大的数字不先打印出来。C 中的类似代码在最顶部给出最大的数字。我缺少关于 Pythonfor循环的东西吗?

仔细研究生产产品的价值会回答您的问题。第一个数字,580085x = 995y = 583产生。同样,第三种产品906609x = 993y = 913生产。循环按预期反向迭代。

碰巧的是,最大的回文不一定需要由最大的乘法生成。

如果要查找最大的回文,请将此函数转换为生成器,并对其调用max。此外,正如评论中指出的那样,您将迭代每对数字两次,一次作为 x-y 对,另一次作为 y-x 对。稍微修改第二个循环,这样就不必执行这些冗余计算。y应该下降到x,而不是100

def foo(l, u):
for x in xrange(u, l, -1):
for y in xrange(u, x - 1, -1):
v = x * y
if str(v) == str(v)[::-1]:
yield v

这样称呼它:

>>> max(foo(100, 999))
906609

对于 python-3.x,请将xrange更改为range


我也很好奇,当你谈论C代码给你预期的输出时,你的意思是什么。所以我写了一点代码来测试:

#include <stdio.h>
#include <string.h>
char buf[42];
# https://stackoverflow.com/a/31397607/4909087
int is_palindrome(char const* s)
{
int len = strlen(s);
if ( len == 0 ) // An empty string a palindrome
{
return 1;
}
int i = 0;
int j = len-1;
for ( ; i < j; ++i, --j )
{
if ( s[i] != s[j] )
{
// the string is not a palindrome.
return 0;
}
}
// If we don't return from inside the for loop,
// the string is a palindrome.
return 1;
}

int main(){    
int x, y; 
for (x = 999; x >= 100; x--)
for (y = 999; y >= 100; y--) 
{
sprintf(buf, "%d", x * y);
if(is_palindrome(buf)){
printf("%dn", x * y);
}    
}
return 0;
}

编译并运行此结果:

$ gcc test.c
$ ./a.out
580085
514415
906609
119911
282282
141141
853358
650056
601106
592295
543345
485584
...

这与你通过python程序得到的数字完全相同。请注意,这仍然效率低下,正确的方法是将内部循环的定义更改为for (y = 999; y >= x; y--)

这样做的诀窍是循环从内部循环迭代到外部循环。首先,对于外部循环,使用值 999 迭代内部循环,然后迭代内部循环,对于外部循环的值为 998。

生成的乘积不是按递减顺序排序的(例如 995 * 583 <993 * 913,但第一个乘积计算得更早,因为 x(乘积的第一个元素)更高(外循环))。

虽然已经有更好的答案,但只需发布输出是如何生成的。 我刚刚修改了 Py3 的代码。正如其他人所解释的那样,这种行为是正常的。由于外循环的 x 值将减少 1,因此只有当内循环的 y 达到 100 时,您看到的输出不是降序的。

for x in range(999,100,-1):
for y in range(999,100,-1):
product= (x*y)
if str(product)== str(product)[::-1]:
print('x is ' + str(x) + '; y is ' + str(y))
print(product)

输出:

x is 995; y is 583
580085
x is 995; y is 517
514415
x is 993; y is 913
906609
x is 991; y is 121
119911
x is 987; y is 286
282282
x is 987; y is 143
141141
x is 982; y is 869
853358
x is 979; y is 664
650056
x is 979; y is 614
601106
x is 979; y is 605
592295
x is 979; y is 555
543345
x is 979; y is 496
485584
x is 979; y is 446
436634
x is 979; y is 387
378873
x is 979; y is 337
329923
x is 978; y is 418
408804

下面是一个代码版本,它将在你查找时从高到低打印值。

它更优化一些,因为它避免了多余的乘法,并过滤掉了无论如何都可能发生的重复项。 (例如 111*9 == 333*3 == 999)。

我在Python 3中做到了这一点。 您可能需要手动导入 Python 2 的 Set 模块。

def foo():
result = set()
for x in range (999,1,-1):
for y in range (999,x,-1):
product= (x*y)
if str(product)== str(product)[::-1]:
result.add(x*y)
result = list(result)
result = sorted(result,reverse=True)
for i in result:
print(i)
foo()

最新更新