栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

单行Python主生成器

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

单行Python主生成器

尽管看起来像那不是Eratosthenes的筛子。实际上,情况要差得多。筛子是找到素数的最佳算法。

参见http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

编辑
:我已经将修改为单线(最初不是真正的筛网,但现在可能是…):

reduce( (lambda r,x: r-set(range(x**2,N,x)) if (x in r) else r),         range(2,N), set(range(2,N)))

演示:

>>> primesUpTo(N): lambda N: reduce(...)>>> primesUpTo(30){2, 3, 5, 7, 11, 13, 17, 19}

遗憾的是,我认为虽然这在函数式编程语言中会很有效,但由于数据结构(非持久性(共享状态和不可变的))的存在,它在python中可能不那么有效,并且python中的任何筛子都需要使用突变来实现可比的性能。如果我们非常想这样做,我们仍然可以将其填充为单线。但首先…

普通筛:

>>> N = 100>>> table = list(range(N))>>> for i in range(2,int(N**0.5)+1):...     if table[i]:...         for mult in range(i**2,N,i):...  table[mult] = False... >>> primes = [p for p in table if p][1:]>>> primes[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

现在,我们可以在同一行上定义和调用匿名函数,以及

[...].__setitem__
进行内联突变的hack和在返回时
... andfoo
求值的hack :
...``foo

>>> primesUpTo = lambda N: (lambda table: [[table.__setitem__(mult,False) for mult in range(i**2,N,i)] for i in range(2,int(N**0.5)+1) if table[i]] and [p for p in table if p][1:])(list(range(N)))>>> primesUpTo(30)[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

令人恐惧的是,单线扩展了(这很漂亮,因为您几乎可以直接转换控制流,但是对所有内容的滥用却很糟糕):

lambda N:    (lambda table:         [[table.__setitem__(mult,False) for mult in range(i**2,N,i)]  for i in range(2,int(N**0.5)+1) if table[i]]         and [p for p in table if p][1:]    )(list(range(N)))

在我的机器上,这种单线变异版本放弃了大约10 8,而原始变异版本放弃了大约10 9,导致内存不足(奇怪)。

原始

reduce
版本在10 7放弃。因此,也许毕竟不是 那么 低效(至少对于您可以在计算机上处​​理的数字而言)。

edit2 似乎您可以更简洁地滥用副作用,例如:

reduce( (lambda r,x: (r.difference_update(range(x**2,N,x)) or r)          if (x in r) else r),         range(2,N), set(range(2,N)))

它放弃了大约10 8,与单线变异版本相同。

edit3:
这以O(N)的经验复杂度运行,而没有

difference_update
它,则以O(n
^ 2.2)的复杂度运行

将缩小的范围限制为上限的平方根,并且仅使用赔率进行处理,两者都会导致额外的提速(分别为 2
1.6倍 ):

reduce( (lambda r,x: (r.difference_update(range(x*x,N,2*x)) or r)          if (x in r) else r),         range(3, int((N+1)**0.5+1), 2),        set([2] + range(3,N,2)))


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/669248.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号