问题:迭代一个整数并在其中找到其他整数的最佳方法是什么,然后如果它包含它们则扔掉那个整数?
长版:
我一直在研究我的Python技能,试图为Project Euler的问题提供有效的解决方案。在经历了大约20个问题后,我发现虽然我可以解决问题,但我的解决方案往往不够优雅和笨重(即丑陋和缓慢)。问题的结构方式,我认为我需要学习一些更好的解决方案,因为更复杂的东西会加剧这些低效率。
无论如何,今天我正在研究问题35,它要求所有低于1,000,000的循环素数。我已经制作了一份低于1,000,000的所有素数的列表,我建立了一个小框架,用于吐出下面这些素数的排列,我计划测试其中的每一个素数:
def number_switcher(number):
number = [num for num in str(number)]
numlist = [''.join(num) for num in list(itertools.permutations(number))]
return [int(num) for num in numlist]
在所有素数上运行此项,然后测试每种可能的素数排列,正如您所能想象的那样,无法解决问题。
然后我突然意识到,在我开始运行排列之前,我可以扔掉所有数字中的数字(假设它们长于一位数)或者其中包含五位数的数字。
这是我真正迷失的地方。虽然看起来很简单,但是经过两天的尝试后,我无法弄清楚如何丢弃任何带有偶数或5位数的多位数字。
这是我尝试的(假设所有素数低于1,000,000的名单在这里称为“素数”):
[num for num in primes if any(x for x in '024685' in str(num))] # failed: 'bool' object is not iterable
然后我尝试了以下内容:
for prime in primes:
if '0' in str(prime):
primes.remove(prime)
>>>>len(primes)
4264
这使我的素数列表减半。好的,所以也许我在正确的轨道上,我只需要一个丑陋的“if'0'在str(素数)或者如果'2'在str(素数),”等等。
但是这里有一个奇怪的事情:当我检查我的'素数'列表时,它仍然有'0'的素数。在新的素数列表上再次运行相同的东西,我得到以下结果:
for prime in primes:
if '0' in str(prime):
primes.remove(prime)
>>>>len(primes)
4026
......结果再次落到:
>>>>len(primes)
3892
....
3861 # again
....
3843 #and again
也许我在这里遗漏了一些明显的东西,但似乎首先if-test应该找到任何带有'0'的素数并删除所有素数?
最后,我也尝试了以下内容,这看起来很糟糕,因为它在str整数列车轨道上来回无意义地跳跃,但它似乎只是必须工作:
for num in primes:
for d in str(num):
if (int(d) % 2 == 0 or int(d) == 5):
primes.remove(num) # doesn't work: ValueError: list.remove(x): x not in list
else:
pass
我觉得我不应该在这个问题上撕裂我的头发,但它让我有点疯狂,可能是因为我已经到了一个点,我只是试图解决一个问题,我的尝试变得越来越清醒。
这是我的问题:
迭代一个整数并在其中找到其他整数的最佳方法是什么,然后如果它包含它那么抛出那个愚蠢的整数?
感谢您的帮助/阅读。
脚注: 这是我在这里提出的第一个问题,但我已经从这个网站的指导中受益了几个月了。抱歉,如果这个问题/解决方案是现存的,但我找了它,却无法找到一种方法来拼凑一个解决方案。大多数搜索结果都是“如何判断整数是否均匀”。
答案 0 :(得分:2)
@root是正确的,你对如何优化它的假设是错误的,但我认为指出为什么你所做的不是在Python级别工作是有用的。
您的布尔问题:
[num for num in primes if any(x for x in '024685' in str(num))] # failed: 'bool' object is not iterable
首先评估 '024685' in str(num)
,因此它等同于for x in True
- 这是不可能的。以上内容将写成:
[num for num in primes if not any(ch in '024685' for ch in str(num)]
从str(num)
获取每个字符并检查它是'024685'
中的一个。
您的列表问题:
这里有一条经验法则 - 不要修改你正在迭代的东西。如果您使用dict
尝试此操作,则会引发异常 - 但对于list
,它可能会出现默默错误,但偶尔会中断。
从列表中删除多个值时,最好构建一个仅保留所需值的新列表,例如:
no_zero = [num for num in primes if '0' not in str(num)]
如果你想修改原始素数:
primes[:] = no_zero
由于.remove()
,您的上一个示例也失败了,将上述内容放在一起可以写成:
[num for num in primes if not any(num % i == 0 for i in (2, 5)]
<强>其它强>:
您可能希望考虑将素数存储在set
中 - 因为您不关心素数的顺序,并且会更快地进行成员资格测试。
答案 1 :(得分:0)
谢谢,Jon Clements。我今天能够通过以下脚本解决问题(请注意,我必须确保'024685'剥离器没有剥离出'2'和'5',因为这些是答案的一部分,这让我失去了一段时间...):
import math
import itertools
def prime_test(number):
if all(number % x != 0 for x in range(2, int(math.sqrt(number)) + 1)):
return True
else:
return False
def find_primes(limit):
primes = [2]
for x in range(3, limit + 1, 2):
if prime_test(x):
primes.append(x)
else:
pass
return primes
def circulate(number):
circ_list = [number]
x = 1
while x < len(str(number)):
number = str(number)[1:] + str(number)[0]
circ_list.append(number)
x += 1
return circ_list
def main():
primes = find_primes(1000000)
no_evens = [x for x in primes if not any(ch in '024685' for ch in str(x) if len(str(x)) > 1)]
circular_primes = []
for prime in no_evens:
if all(prime_test(x) for x in circulate(prime)):
circular_primes.append(prime)
else:
pass
return circular_primes, len(circular_primes)
if __name__ == '__main__':
print(main())
我没有意识到的另一件事是我只是应该旋转数字,而不是提供它的所有可能的排列。当他们试图解决问题时,这些问题可能会让人失望。