Python 使用常量空间迭代所有互质对?
我可以按照维基百科上列出的三元树算法生成所有互质对: 很快:Python 使用常量空间迭代所有互质对?,python,algorithm,primes,ternary-tree,Python,Algorithm,Primes,Ternary Tree,我可以按照维基百科上列出的三元树算法生成所有互质对: 很快: Start with two coprime branches: (2,1), (3,1), then iterate: Branch 1: (2m-n,m) Branch 2: (2m+n,m) Branch 3: (m+2n,n) 然而,每生产一对(比如说打印的,或者没有保存在内存中的),所使用的空间将增加三倍 在haskell中可能有一个解决方案: 但是我在python中寻找一些东西,它没有惰性求值或无限列表。公认的Has
Start with two coprime branches: (2,1), (3,1), then iterate:
Branch 1: (2m-n,m)
Branch 2: (2m+n,m)
Branch 3: (m+2n,n)
然而,每生产一对(比如说打印的,或者没有保存在内存中的),所使用的空间将增加三倍
在haskell中可能有一个解决方案:
但是我在python中寻找一些东西,它没有惰性求值或无限列表。公认的Haskell解决方案的python版本
def find_coprimes():
l = 1
while True:
i = 2
while i < l-i:
if gcd(i, l-i) == 1:
yield i, l-i
i += 1
l += 1
输出:
(2, 3)
(2, 5)
(3, 4)
(3, 5)
(2, 7)
(4, 5)
(3, 7)
(2, 9)
(3, 8)
(4, 7)
公认的Haskell解决方案的Python版本
def find_coprimes():
l = 1
while True:
i = 2
while i < l-i:
if gcd(i, l-i) == 1:
yield i, l-i
i += 1
l += 1
输出:
(2, 3)
(2, 5)
(3, 4)
(3, 5)
(2, 7)
(4, 5)
(3, 7)
(2, 9)
(3, 8)
(4, 7)
这使用对数空间,也许这就足够了?它是线性时间(使用O(k)时间产生前k对) 在David Eppstein的这些文章中,您可以阅读有关此类自递归生成器的更多信息:
>>> pairs = coprimes()
>>> for _ in range(20):
print(next(pairs))
(2, 1)
(3, 1)
(3, 2)
(5, 2)
(4, 1)
(5, 3)
(7, 3)
(5, 1)
(4, 3)
(8, 3)
(7, 2)
(8, 5)
(12, 5)
(9, 2)
(7, 4)
(9, 4)
(6, 1)
(7, 5)
(13, 5)
(11, 3)
演示显示了第十亿对的内存,这需要我的电脑大约4分钟,而Python进程的内存使用量保持在任何Python进程至少需要9.5 MB的基线
>>> from itertools import islice
>>> next(islice(coprimes(), 10**9-1, None))
(175577, 63087)
这使用对数空间,也许这就足够了?它是线性时间(使用O(k)时间产生前k对) 在David Eppstein的这些文章中,您可以阅读有关此类自递归生成器的更多信息:
>>> pairs = coprimes()
>>> for _ in range(20):
print(next(pairs))
(2, 1)
(3, 1)
(3, 2)
(5, 2)
(4, 1)
(5, 3)
(7, 3)
(5, 1)
(4, 3)
(8, 3)
(7, 2)
(8, 5)
(12, 5)
(9, 2)
(7, 4)
(9, 4)
(6, 1)
(7, 5)
(13, 5)
(11, 3)
演示显示了第十亿对的内存,这需要我的电脑大约4分钟,而Python进程的内存使用量保持在任何Python进程至少需要9.5 MB的基线
>>> from itertools import islice
>>> next(islice(coprimes(), 10**9-1, None))
(175577, 63087)
该问题没有说明生成的互质对的条件(例如,其中一个数是否在特定范围内?)。然而,我发现下面两个例子很有趣(都需要恒定的空间)
首先考虑,这里是Python 3中的一个例子:
a, b, c, d = 0, 1, 1, n
while c <= n:
k = (n + b) // d
a, b, c, d = c, d, k * c - a, k * d - b
print(a, b)
如果你想找到一个满足某些性质的有理数的例子,但你不知道它的边界,这可能很方便。当然,您可以尝试所有可能的自然数对,但这会直接生成互质对。问题不会说明生成的互质对的条件(例如,其中一个数是否在特定范围内?)。然而,我发现下面两个例子很有趣(都需要恒定的空间)
首先考虑,这里是Python 3中的一个例子:
a, b, c, d = 0, 1, 1, n
while c <= n:
k = (n + b) // d
a, b, c, d = c, d, k * c - a, k * d - b
print(a, b)
如果你想找到一个满足某些性质的有理数的例子,但你不知道它的边界,这可能很方便。当然,您可以尝试所有可能的自然数对,但这会直接生成互质对。请澄清:您想要与Haskell问题相同的限制吗<代码>每对中的第一个元素必须小于第二个元素。排序必须按升序进行——按对的元素之和;如果两个和相等,则通过对的第一个元素进行交换。如果是,则要在算法中交换这些对。Python确实有无限的生成器,这可能与您的“无限列表”类似。您是在试图避免“增长三倍”的问题,还是只需要简单的Python代码?“但我在Python中寻找一些东西,它没有惰性求值或无限列表。”Python有生成器(惰性地生成值)和函数(尤其是在
itertools
中),它们产生潜在的无限序列。我不是在寻找haskell解决方案的限制,我应该说。任何惯用的python解决方案都可以工作,而不管懒惰/无限的术语如何<代码>每对中的第一个元素必须小于第二个元素。排序必须按升序进行——按对的元素之和;如果两个和相等,则通过对的第一个元素进行交换。如果是,则要在算法中交换这些对。Python确实有无限的生成器,这可能与您的“无限列表”类似。您是在试图避免“增长三倍”的问题,还是只需要简单的Python代码?“但我在Python中寻找一些东西,它没有惰性求值或无限列表。”Python有生成器(惰性地生成值)和函数(尤其是在itertools
中),它们产生潜在的无限序列。我不是在寻找haskell解决方案的限制,我应该说。而且任何惯用的python解决方案都可以工作,不管懒惰/无限的术语是什么。这要优雅得多,应该被接受!信息链接。是的,谢谢,这是一个优雅的解决方案,我不知道你能用迭代器做到这一点。很漂亮。我高兴得流下了眼泪。这更优雅,应该被接受!信息链接。是的,谢谢,这是一个优雅的解决方案,我不知道你能用迭代器做到这一点。很漂亮。我高兴得流下了眼泪。