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

时间:2018-01-22 09:39:46

标签: python python-2.7

我为project Euler question #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中的类似代码在最顶部给出了最大的数字。我缺少Python for循环吗?

4 个答案:

答案 0 :(得分:1)

仔细研究产生该产品的价值会回答您的问题。第一个数字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("%d\n", 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--)

答案 1 :(得分:0)

这方面的技巧是循环从内循环迭代到外循环。首先,对于外部循环迭代内部值为999,然后为外部循环迭代内部循环以获得值998。

由此产生的产品不按降序排序(例如995 * 583&lt; 993 * 913,但由于x(产品的第一个元素)较高(外环),因此第一个产品计算得更早。)

答案 2 :(得分:0)

虽然已有更好的答案,但只发布输出的生成方式。 我刚修改了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

答案 3 :(得分:0)

这是您的代码版本,可以根据您的需要打印从最高到最低的值。

它更加优化,因为它避免了冗余乘法,并滤除了无论如何都会发生的重复。 (例如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()