Python 我能';我不知道我哪里做错了:(
我正在用python研究euler项目的问题23。对于这个问题,我必须找到任何数字的总和,只是为了获得一些经验,你真的应该看看理解并利用内置项(与隐藏它们相比): 在Python 我能';我不知道我哪里做错了:(,python,Python,我正在用python研究euler项目的问题23。对于这个问题,我必须找到任何数字的总和,只是为了获得一些经验,你真的应该看看理解并利用内置项(与隐藏它们相比): 在dSum()(也可以简化)之外的循环可以如下所示: import itertools as it abnum = [i for i in range(1,28124) if i < dSum(i)] can = {i+j for i, j in it.product(abnum, repeat=2)} cannot = s
dSum()
(也可以简化)之外的循环可以如下所示:
import itertools as it
abnum = [i for i in range(1,28124) if i < dSum(i)]
can = {i+j for i, j in it.product(abnum, repeat=2)}
cannot = set(range(1,28124)) - can
print(sum(cannot)) # 4179871
按需要导入itertools
如果i
有几种方法可以改进代码
首先,这里有一个更紧凑的dSum
版本,它与您的代码非常接近。运算符通常比函数调用快,因此我使用**.5
而不是调用math.sqrt
。我使用条件表达式而不是if…else
块来计算步长。我使用内置的求和
函数而不是for
循环来累加除数;另外,我使用整数减法从总数中删除n
,因为这比调用set.remove方法更有效
def dSum(n):
lst = set()
for i in range(1, int(n ** .5) + 1, 2 if n % 2 else 1):
if n % i == 0:
lst.add(i)
lst.add(n // i)
return sum(lst) - n
然而,我们实际上不需要在这里使用集合。我们可以在找到除数对时添加它们,如果我们小心不要将任何除数添加两次的话
def dSum(n):
total = 0
for i in range(1, int(n ** .5) + 1, 2 if n % 2 else 1):
if n % i == 0:
j = n // i
if i < j:
total += i + j
else:
if i == j:
total += i
break
return total - n
如果我们需要为一个非常大的num
找到除数和,一个很好的方法是找到每个数字的素幂因子,因为有一种有效的方法可以通过素幂因子分解计算除数和。然而,对于这么小的数,节省的时间不足以保证额外的代码复杂性。(如果你好奇的话,我可以添加一些素数幂筛代码;对于所有小于28124的数字,要找到除数和,素数幂筛技术的速度大约是上述代码的两倍)
AChampion的答案显示了一种非常简洁的方法,可以找到不能写成两个富足数之和的数之和。但是,它有点慢,主要是因为它在abnum
中循环所有富足数对。这里有一种更快的方法
def main():
num = 28124
# Build a table of divisor sums. table[0] should be 0, but we ignore it.
table = [1] * num
for i in range(2, num):
for j in range(2 * i, num, i):
table[j] += i
# Collect abundant numbers
abnum = [i for i in range(2, num) if i < table[i]]
del table
# Create a set for fast searching
abset = set(abnum)
print(len(abset), abnum[0], abnum[-1])
total = 0
for i in range(1, num):
# Search for pairs of abundant numbers j <= d: j + d == i
for j in abnum:
d = i - j
if d < j:
# No pairs were found
total += i
break
if d in abset:
break
print(total)
if __name__ == "__main__":
main()
这段代码在运行Python 3.6.0的旧32位单核2GHz机器上运行大约2.7秒。在Python 2上,速度大约快10%;我认为这是因为列表理解在Python 2中的开销较小(在当前范围内运行,而不是创建新范围).这不是一个很好的问题。请尝试一下代码审查的机会,然后发布代码。@LaurentPorte因为代码现在已经发布了,但它不起作用,这是一个很好的问题,尽管不是一个很好的问题。请解释什么是Euler问题23。一个问题应该尽可能独立,谢谢@Johncolman的提示。我只是ndering是否有任何方法可以直接复制粘贴代码,而不必手动为所有行添加4个空格?当我不覆盖内置名称(如sum
)时,当我不将集合命名为lst
时,请删除本地未使用的变量(如llst
),并尝试用python编写更多pythonic.Maybe查找sum()
也能为您做些什么;-)
num = 28124
# Build a table of divisor sums.
table = [1] * num
for i in range(2, num):
for j in range(2 * i, num, i):
table[j] += i
# Collect abundant numbers
abnum = [i for i in range(2, num) if i < table[i]]
print(len(abnum), abnum[0], abnum[-1])
6965 12 28122
def main():
num = 28124
# Build a table of divisor sums. table[0] should be 0, but we ignore it.
table = [1] * num
for i in range(2, num):
for j in range(2 * i, num, i):
table[j] += i
# Collect abundant numbers
abnum = [i for i in range(2, num) if i < table[i]]
del table
# Create a set for fast searching
abset = set(abnum)
print(len(abset), abnum[0], abnum[-1])
total = 0
for i in range(1, num):
# Search for pairs of abundant numbers j <= d: j + d == i
for j in abnum:
d = i - j
if d < j:
# No pairs were found
total += i
break
if d in abset:
break
print(total)
if __name__ == "__main__":
main()
6965 12 28122
4179871