Что ж, в моем воображении такой подход был бы оптимальным:
- делится только с (уже) известными простыми числами (а не с каждым числом)
- до квадрата root данное число
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))
Затем наступает увеличение делает его lambda
part
isprime=lambda n:all(n%p!=0 for p in primes)
работает, но оно пропускает sqrt
magi c, затем
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()
дважды пересекают часть списка.
Затем приходит внешний l oop, я бы используйте 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
Выводное сообщение будет таким: лямбды могут быть полезны, но на самом деле вам не всегда нужно их использовать.