使用Python,我试图解决problem #4问题的Project Euler。有人可以告诉我我做错了什么吗?问题是找到由两个3位数字的产品制成的最大回文。这是我到目前为止所做的。
import math
def main():
for z in range(100, 1000):
for y in range(100, 1000):
for x in range(1, 1000000):
x = str(x)
if x == x[::-1] and x == z*y:
print x
if __name__ == '__main__':
main()
答案 0 :(得分:10)
一些效率问题:
def is_palindrome(n): s = str(n) return s == s[::-1] def biggest(): big_x, big_y, max_seen = 0,0, 0 for x in xrange(999,99,-1): for y in xrange(x, 99,-1): # so we don't double count if x*y < max_seen: continue # since we're decreasing, # nothing else in the row can be bigger if is_palindrome(x*y): big_x, big_y, max_seen = x,y, x*y return big_x,big_y,max_seen biggest() # (993, 913, 906609)
答案 1 :(得分:9)
尝试从z和y的乘积计算x,而不是检查从1到100的每个数字。想一想:如果你被要求计算500 * 240,哪个更有效 - 乘以它们,或从1开始计算直到找到正确的答案?
答案 2 :(得分:4)
以下是一些要记住的一般优化。发布的代码处理所有这些,但这些是可以帮助解决未来问题的一般规则:
1)如果你已经检查过z = 995,y = 990,你不需要检查z = 990,y = 995.Greg Lind正确处理这个
2)你计算z * y的乘积然后你在一个巨大的范围内运行x并将该值与y * z进行比较。例如,您刚刚计算了900 * 950,然后将x从1000运行到1M,并查看x = 900 * 950。你看到了这个问题吗?
3)此外,以下代码会发生什么? (这就是为什么你的代码什么也没有返回,但你不应该这样做)
x = str(100)
y = 100
print x == y
4)如果你弄清楚(3),你将在那里打印很多信息。您需要找出存储最大值的方法,并且最后只返回该值。
5)这是计算欧拉问题的好方法:
if __name__ == "__main__":
import time
tStart = time.time()
print "Answer = " + main()
print "Run time = " + str(time.time() - tStart)
答案 3 :(得分:1)
将字符串与
中的整数进行比较x == z*y
还存在逻辑错误
以相反的顺序range(999, 99, -1)
开始。那会更有效率。完全删除第三个循环和第二个比较。
答案 4 :(得分:1)
而不是枚举所有3位数字的产品(约900 ^ 2次迭代), 列举所有6位和5位数的palyndromes(这需要大约1000次迭代); 然后对每个palyndrome决定它是否可以由产品代表 两个3位数字(如果不能,它应该有一个4位数的素数因子, 所以这很容易测试。)
另外,你问的问题是#4,而不是#3。
答案 5 :(得分:0)
问题陈述:
What is the largest prime factor of the number 600851475143?
我使用C#解决了这个问题,但算法本身与语言无关。
private static long IsPrime(long input)
{
if ((input % 2) == 0)
{
return 2;
}
else if ((input == 1))
{
return 1;
}
else
{
long threshold = (Convert.ToInt64(Math.Sqrt(input)));
long tryDivide = 3;
while (tryDivide < threshold)
{
if ((input % tryDivide) == 0)
{
Console.WriteLine("Found a factor: " + tryDivide);
return tryDivide;
}
tryDivide += 2;
}
Console.WriteLine("Found a factor: " + input);
return -1;
}
}
private static long HighestPrimeFactor(long input)
{
bool searching = true;
long highestFactor = 0;
while (searching)
{
long factor = IsPrime(input);
if (factor != -1)
{
theFactors.Add(factor);
input = input / factor;
}
if (factor == -1)
{
theFactors.Add(input);
highestFactor = theFactors.Max();
searching = false;
}
}
return highestFactor;
}
我希望这会有所帮助,而不会放弃太多。
答案 6 :(得分:0)
这里的其他建议很棒。此代码也有效。我从999开始,因为我们知道可能的最大组合是999 * 999。不是python,而是一些快速完成的伪代码。
public static int problem4()
{
int biggestSoFar=0;
for(int i = 999; i>99;i--){
for(int j=999; j>99;j--){
if(isPaladrome(i*j))
if(i*j>biggestSoFar)
biggestSoFar=i*j;
}
}
return biggestSoFar;
}
答案 7 :(得分:0)
这是您可能考虑的解决方案。它可能效率更高,但只需要一点时间就可以运行。
largest = 0
for a in range(100, 1000):
for b in range(100, 1000):
c = a * b
if str(c) == ''.join(reversed(str(c))):
largest = max(largest, c)
print(largest)
答案 8 :(得分:0)
这是一个有效的通用解决方案(比我见过的其他人快〜5倍):
def pgen(factor):
''' Generates stream of palindromes smaller than factor**2
starting with largest possible palindrome '''
pmax = str(factor**2)
half_palindrome = int(pmax[0:len(pmax)/2]) - 1
for x in xrange(half_palindrome, 0, -1):
yield int(str(x) + str(x)[::-1])
def biggest(factor):
''' Returns largest palindrome and factors '''
for palindrome in pgen(factor):
for f1 in xrange(factor/11*11, factor/10, -11):
f2 = palindrome/f1
if f2 > factor:
break
if f2*f1 == palindrome:
return palindrome, f1, f2
>>> biggest(99)
(9009, 99, 91)
>>> biggest(999)
(906609, 993, 913)
>>> biggest(9999)
(99000099, 9999, 9901)
>>> biggest(99999)
(9966006699L, 99979, 99681L)
>>> biggest(9999999)
(99956644665999L, 9998017, 9997647L)
>>> biggest(99999999)
(9999000000009999L, 99999999, 99990001L)
>>> biggest(999999999)
(999900665566009999L, 999920317, 999980347L)
答案 9 :(得分:-1)
如果你的程序运行缓慢,并且你有这样的嵌套循环:
for z in range(100, 1000):
for y in range(100, 1000):
for x in range(1, 1000000):
然后你应该问自己的问题是:“最内层循环的主体会执行多少次?” (最内层循环的主体是以:x = str(x)
)
在这种情况下,很容易弄明白。外循环将执行900次。 对于每次迭代,中间循环也将执行900次 - 这使得900×900或810,000次。然后,对于810,000次迭代中的每次迭代,内部循环本身将执行999,999次。我想我需要很长时间来计算:
>>> 900*900*999999
809999190000L
换句话说,你的回文检查几乎达到了810亿次次。如果你想使每个问题的项目欧拉建议限制为1分钟,你可能想要优化一点:-)(参见David的评论)
答案 10 :(得分:-1)
这就是我在Java中所做的:
public class Euler0004
{
//assumes positive int
static boolean palindrome(int p)
{
//if there's only one char, then it's
// automagically a palindrome
if(p < 10)
return true;
char[] c = String.valueOf(p).toCharArray();
//loop over the char array to check that
// the chars are an in a palindromic manner
for(int i = 0; i < c.length / 2; i++)
if(c[i] != c[c.length-1 - i])
return false;
return true;
}
public static void main(String args[]) throws Exception
{
int num;
int max = 0;
//testing all multiples of two 3 digit numbers.
// we want the biggest palindrome, so we
// iterate backwards
for(int i = 999; i > 99; i--)
{
// start at j == i, so that we
// don't calc 999 * 998 as well as
// 998 * 999...
for(int j = i; j > 99; j--)
{
num = i*j;
//if the number we calculate is smaller
// than the current max, then it can't
// be a solution, so we start again
if(num < max)
break;
//if the number is a palindrome, and it's
// bigger than our previous max, it
// could be the answer
if(palindrome(num) && num > max)
max = num;
}
}
//once we've gone over all of the numbers
// the number remaining is our answer
System.out.println(max);
}
}
答案 11 :(得分:-1)
这是我的解决方案:
polindroms = [(x, y, x * y) for x in range(100, 999) for y in range(100, 999) if str(x * y) == str(x * y)[::-1]]
print max(polindroms, key = lambda item : item[2])