在运行python程序时检查空闲状态 - Euler#41

时间:2013-07-09 21:36:24

标签: python optimization permutation

我想找到Spoiler alert Euler #41 problem的解决方案。我问过的问题是它的子问题。我有问题的解决方案,但问题在于解决方案。这是我要检查的实际内容: -

large = 0
x = ''

for i in range(1,10):
x += '%d' %i
for perm in permutations(x):
    if(isPrime(int(perm))):
        large = perm

print large

这里是排列函数: -

def permutations(val):
    res = []
    if len(val) == 1:
        res = [val]
    else:
        for i, c in enumerate(val):
            for perm in permutations(val[:i]+val[i+1:]):
                res += [c+perm]

return res

上述程序从1到987654321找到排列中所有素数的排列。

但问题是在大= 7652413之后,没有进一步的增长。程序在大约3秒内达到此值,但程序在大约4分钟内完成。所以我想知道是否有任何方法可以减少时间。

这个问题也可以概括为一种方法,可以找出一个函数,它告诉你函数是否花费太长时间来获得所需的结果。

2 个答案:

答案 0 :(得分:2)

只回答手头的直接问题,您可以使用itertools.permutations显着加快代码速度。

但是,从数学上讲,你可以通过意识到你想要的素数最多可以有7位来减少你的问题。如果它有8,那么1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 = 36,它可以被3整除,所以不能是素数。添加9得到45,也可以被3整除。

答案 1 :(得分:1)

听起来你正在寻找一种方法来应用超时作为启发式来告诉你“你可能已经完成”,然后停止工作。

这样做的简单方法是在开始时或每次增加large时获取当前时间(取决于您认为相关的那个),然后经常检查时间并取消如果你经过它。

如果在你的代码中手动“经常检查”是不合理的,你可以使用后台线程来做,但让我们保持简单,因为这里似乎没有必要。

所以:

class Timeout(object):
    def __init__(self, timeout_seconds):
        self.timeout = datetime.timedelta(0, timeout_seconds)
        self.reset()
    def reset(self):
        self.start = datetime.datetime.now()
        self.stop = self.start + self.timeout
    def check(self):
        if datetime.datetime.now() > self.stop:
            raise Exception('Timeout!')

现在,你可以这样做:

t = Timeout(30)
for perm in permutations(x):
    if isPrime(int(perm)):
        large = perm
        t.reset()
    t.check()

如果你想使用自更新以来的循环次数而不是秒数,或者某些更高级的启发式算法,那就没那么复杂了。您只需要描述启发式,然后将其转换为代码。