嗯,在我的想象中,这种方法是最佳的
- 只用(已经)已知的素数(而不是每个数字)除法
- 直到给定数字的平方根
import math
primes=[2]
def isprime(n): # NB! this is fragile,
s=int(math.sqrt(n)) # relies on `primes` being
for p in primes: # already fully grown
if n%p==0: # up to the sqrt(n)
return False
if p>s:
return True
maxn=19
for i in range(3,maxn+1):
if isprime(i):
primes.append(i)
print(primes)
print(sum(primes))
然后是 uglification 使其成为lambda 部分
isprime=lambda n:all(n%p!=0 for p in primes)
有效,但它错过了 sqrt 魔法,然后
isprime=lambda n:all(n%p!=0 for p in (p for p in primes if p<=int(math.sqrt(n))))
它为所有已知的素数计算 int(math.sqrt(n)),但这可能是一个一次性参数,对于 filter() 或内部 lambda(后一个显示在这里):
isprime=lambda n:all(n%p!=0 for p in (lambda s:(p for p in primes if p<=s))(int(math.sqrt(n))))
我仍然不喜欢它将所有素数与 s 进行比较的事实,停在中间可能更有效,使用index(next(...)) 获取切片可以做到这一点:
isprime=lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))])
next() 和 index() 两次遍历列表的一部分仍然很难看。
然后是外循环,我将使用reduce() 来表示functools 中的那个,因为归约的累加器可能是实际的素数列表,然后它就不会是一个单独的变量。
第 0 步将以极简的方式实现,仍然使用变量 primes,但使用元组的可怕技巧,(do,some,things,result)[3] 将做这些事情,并评估为 result:
primes=[2]
isprime=lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))])
maxn=19
ps=functools.reduce(lambda primes,n:(primes.append(n) if isprime(n) else None,primes)[1],range(3,maxn+1),primes)
print(ps)
print(primes)
print(sum(primes)) # ps and primes are the same list actually
然后完成怪物:
import math
import functools
plist=lambda maxn:functools.reduce(lambda primes,n:(primes.append(n) if (lambda n:all(n%p!=0 for p in primes[:(lambda s:primes.index(next(p for p in primes if p>s)))(int(math.sqrt(n)))]))(n) else None,primes)[1],range(3,maxn+1),[2])
primes=plist(19)
print(primes)
print(sum(primes))
测试:https://ideone.com/0y7dN9
输出:
[2, 3, 5, 7, 11, 13, 17, 19]
77
外卖信息是:lambdas 可能很有用,但实际上您并不总是必须使用它们。