Possible optimizations for Project Euler #4 algorithm
Find the largest palindrome made from the product of two 3-digit numbers.
号
尽管算法对于手头的问题足够快,但我想知道是否遗漏了任何明显的优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | from __future__ import division from math import sqrt def createPalindrome(m): m = str(m) + str(m)[::-1] return int(m) def problem4(): for x in xrange(999,99,-1): a = createPalindrome(x) for i in xrange(999,int(sqrt(a)),-1): j = a/i if (j < 1000) and (j % 1 == 0): c = int(i * j) return c |
在我的代码中,最大的减速似乎是将一个整数转换为一个字符串,将其反向添加,然后将结果转换回一个整数。
我查找了更多关于回文的信息,偶然发现了这个公式,它允许我将3位数字"n"转换为6位回文数字"p"(可适用于其他数字,但我不担心)。
P=1100*N?990*?n/10??99*?n/100?
我的原始代码在0.75毫秒内运行,而新的代码几乎花费相同的时间(更不用说,公式必须根据"n"的位数进行调整),所以我想没有多少优化需要执行。
当我刚开始学习Python时,我写了这篇文章,但这里是:
1 2 3 4 5 6 7 8 9 10 11 12 | for i in range (999, 800, -1): for j in range (999,800, -1): number = i*j str_number = str(number) rev_str_number = str_number[::-1] if str_number == rev_str_number: print("%s a palendrome") % number |
。
我没有检查你所有的号码,但我还是得到了正确的答案。在这个练习中,我真正学到的是":"以及它的工作原理。你可以在这里看看。
祝欧拉好运!
看看这里有什么想法
在C++中,我这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int euler004() { // A palindromic number reads the same both ways. The largest palindrome // made from the product of two 2-digit numbers is 9009 = 91 99. // Find the largest palindrome made from the product of two 3-digit numbers. const int N=3; const int N2=N<<1; int min,max,a,b,c,i,j,s[N2],aa=0,bb=0,cc=0; for (min=1,a=1;a<N;a++) min*=10; max=(min*10)-1; i=-1; for (a=max;a>=min;a--) for (b=a;b>=min;b--) { c=a*b; if (c<cc) continue; for (j=c,i=0;i<N2;i++) { s[i]=j%10; j/=10; } for (i=0,j=N2-1;i<j;i++,j--) if (s[i]!=s[j]) { i=-1; break; } if (i>=0) { aa=a; bb=b; cc=c; } } return cc; // cc is the output } |
- 不需要sqrt…
createPalindrome 的子调用可以降低由于堆/堆栈垃圾造成的速度。- 串操作
m = str(m) + str(m)[::-1] 慢 - 如果在固定大小数组上进行字符串到int的转换,则转换速度会更快。
- Mine实现大约运行1.7毫秒,但大部分时间是应用程序输出和格式化(w7 x64上的amd 3.2Ghz 32位应用程序)。
- 这需要~0.4 ms
- 这对我来说太快了,无法正确测量时间(原始时间约为0.037 ms)
- 从回文生成中删除了除法和乘法
- 在等待总线时,经过一些数值分析和思考,改变了范围
- 第一个循环可以消除(结果从9开始)
小精灵
[edit1]实现公式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | int euler004() { int i,c,cc,c0,a,b; for (cc=0,i=999,c0=1100*i;i>=100;i--,c0-=1100) { c=c0-(990*int(i/10))-(99*int(i/100)); for(a=999;a>=300;a--) if (c%a==0) { b=c/a; if ((b>=100)&&(b<1000)) { cc=c; i=0; break; } } } return cc; } |
号
小精灵
[edit2]进一步优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //--------------------------------------------------------------------------- int euler004() { // A palindromic number reads the same both ways. The largest palindrome // made from the product of two 2-digit numbers is 9009 = 91 99. // Find the largest palindrome made from the product of two 3-digit numbers. int i0,i1,i2,c0,c1,c,cc=0,a,b,da; for (c0= 900009,i0=9;i0>=1;i0--,c0-=100001) // first digit must be non zero so <1,9> for (c1=c0+90090,i1=9;i1>=0;i1--,c1-= 10010) // all the rest <0,9> for (c =c1+ 9900,i2=9;i2>=0;i2--,c -= 1100) // c is palindrome from 999999 to 100001 for(a=999;a>=948;a-- ) if (c%a==0) { // biggest palindrome is starting with 9 // so smallest valid result is 900009 // it is odd and sqrt(900009)=948 so test in range <948,999> b=c/a; if ((b>=100)&&(b<1000)) { cc=c; i0=0; i1=0; i2=0; break; } } return cc; } //--------------------------------------------------------------------------- |
小精灵