加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 关于滑动窗口和memoization的计算

发布时间:2020-12-16 22:03:57 所属栏目:Python 来源:网络整理
导读:我正在研究Project Euler Problem 50,它指出: The prime 41,can be written as the sum of six consecutive primes: 41 = 2 + 3 + 5 + 7 + 11 + 13 This is the longest sum of consecutive primes that adds to a prime below one-hundred. The longest su

我正在研究Project Euler Problem 50,它指出:

The prime 41,can be written as the sum of six consecutive primes:

41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below one-hundred.

The longest sum of consecutive primes below one-thousand that adds to a prime,contains 21 terms,and is equal to 953.

Which prime,below one-million,can be written as the sum of the most consecutive primes?

为了确定素数P中的项(如果它可以写成素数的总和),我使用所有素数的滑动窗口(按递增顺序)直到(但不包括)P,并计算所有的总和这些窗口,如果总和等于考虑的素数,我算一下窗口的长度……

这适用于1000以下的所有素数,但是对于高达10 ** 6的素数来说它非常慢,所以我希望备忘录会有所帮助;在计算滑动窗口的总和时,做了很多双重工作……(对吧?)

所以我在网上找到了标准的memoizaton实现,并将其粘贴在我的代码中,这是正确的吗? (我不知道应该怎么在这里工作……)

primes = tuple(n for n in range(1,10**6) if is_prime(n)==True)

count_best = 0


##http://docs.python.org/release/2.3.5/lib/itertools-example.html:
## Slightly modified (first for loop)
from itertools import islice
    def window(seq):
    for n in range(2,len(seq) + 1):

        it = iter(seq)
        result = tuple(islice(it,n))
        if len(result) == n:
            yield result    
        for elem in it:
            result = result[1:] + (elem,)
            yield result   

def memoize(function):
    cache = {}
    def decorated_function(*args):
        if args in cache:
            return cache[args]
        else:
            val = function(*args)
            cache[args] = val
            return val
    return decorated_function


@memoize 


def find_lin_comb(prime):
    global count_best

    for windows in window(primes[0 : primes.index(prime)]):
        if sum(windows) == prime and len(windows) > count_best:
            count_best = len(windows)
            print('Prime: ',prime,'Terms: ',count_best)


##Find them:
for x in primes[::-1]: find_lin_comb(x)

(顺便说一句,素数的元组是“正常”快速生成的)

所有的输入都很受欢迎,我只是一个业余爱好程序员,所以请不要对我有所了解.

谢谢!

编辑:这是一个没有破坏缩进的工作代码粘贴:
http://pastebin.com/R1NpMqgb

最佳答案

This works fine for all primes up to 1000,but for primes up to 10**6 it is very slow,so I was hoping memozation would help; when calculating the sum of sliding windows,a lot of double work is done…(right?)

是的,对.当然,对于高达106的素数而言,它的速度很慢.

假设您有n个素数到N,按递增顺序编号,p_1 = 2,p_2 = 3,….当考虑是否素数没有. k是连续素数的总和,你考虑所有窗口[p_i,…,p_j],对于对(i,j),其中i <1. j< ?.它们有(k-1)*(k-2)/ 2.通过所有k到n,你总共检查了n3/ 6个窗口(计算多重性,你在总共n-j次检查w(i.j)).即使忽略创建窗口并对其进行求和的成本,您也可以看到它如何严重缩放:
>对于N = 1000,要检查n = 168个素数和约790000个窗口(计算多重性).
>对于N = 10 ** 6,有n = 78498个素数和大约8.3 * 10 ** 13个窗口需要检查.

现在考虑创建和求和窗口的工作,估计它在ji 1低,用于求和w(i,j)中的ji 1素数,p_k的工作约为k3/ 6,总工作量大约为k * * 4/24中. N = 1000,花生等3300万步,但N = 1000000,接近1.6 * 10 ** 18.

一年包含大约3.1 * 10 ** 7秒,具有~3GHz的CPU,大约1017个时钟周期.所以我们谈论的是需要100个CPU年的操作(可能是10个左右的因素).

你想,你不愿意等那么久;)

现在,通过记忆,你仍然可以多次查看每个窗口,但是你只对每个窗口进行一次计算.这意味着您需要大约n3/ 6的工作来计算窗口,并在任何窗口看一下n3/ 6次.

>问题1:您仍需要查看大约8.3 * 10 ** 13次的窗口,即使只花费一个周期,也需要几个小时.
>问题2:有大约8.3 * 10 ** 13个窗口要记忆.你没有那么多的记忆,除非你可以使用一个非常大的高清.

您可以通过丢弃不再需要的数据来规避内存问题,并且只在需要时计算窗口的数据,但是一旦您知道可能会丢弃哪些数据,您应该能够看到更好的方法.

The longest sum of consecutive primes below one-thousand that adds to a prime,and is equal to 953.

这告诉你关于产生这笔金额的窗口是什么?哪里可以开始,哪里可以停止?如何使用该信息创建一个有效的算法来解决问题?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读