我的程序需要很长时间才能打印超过25的结果,有没有办法让我在运行时更有效率?

时间:2017-10-20 16:07:53

标签: python math python-3.6

这些是我使用的行,它生成一个列表,列出了总和为输入的整数,然后说明了组合的数量。

import itertools

val = int(input())
r = range(val)[1:]
res = []    
for i in range(len(r)+1):
    res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val]    
print("Solution : %s " % res)
print("Combinations : %s" % len(res))

2 个答案:

答案 0 :(得分:1)

看起来您正在计算每个可能的组合,然后只保留满足您的总和条件的组合。它正在搜索的组合池以2 ^(n-1)的速度增长,您可以通过注释条件部分来查看:

import itertools
import time

startTime = time.time()

val = 21
r = range(val)[1:]
res = []    
for i in range(len(r)+1):
    res += [list(x) for x in itertools.combinations(r, i)]# if sum(list(x)) == val]    
#print("Solution : %s " % res)
print("Combinations : %s" % len(res))

print(time.time() - startTime, 'seconds')

试试这个:

def a(lst, target, with_replacement=False):
    def _a(idx, l, r, t, w):
        if t == sum(l): r.append(l)
        elif t < sum(l): return
        for u in range(idx, len(lst)):
            _a(u if w else (u + 1), l + [lst[u]], r, t, w)
        return r
    return _a(0, [], [], target, with_replacement)

val = 50
s = range(1, val)
solutions = a(s, val)
print(solutions)
print(len(solutions))

由thefourtheye代码修改: Finding Combinations to the provided Sum value

计时: 原始代码:

val = 24, t = 6.5917372703552253 seconds
val = 25, t = 13.705767631530762 seconds
val = 26, t = 27.934977531433105 seconds
val = 50, t = 459889248.39282094 seconds

上述方法:

val = 24, t = 0.0084612369537353 seconds
val = 25, t = 0.0069310665130615 seconds
val = 26, t = 0.0085859298706054 seconds
val = 50, t = 0.4947729110717773 seconds

答案 1 :(得分:1)

可能有很多方法可以提高速度。我试过(并注意到它有很大的不同)一个简单的方法:摆​​脱生成器和列表之间的重复转换。这是您的代码,已修改:

import time
import itertools

#val = int(input("val:"))
#r = range(val)[1:]

def simple_time_func(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        r = func(*args, **kwargs)
        print("{} took {:.3f} seconds.".format(func.__name__, time.time() - start))
        return r
    return wrapper

@simple_time_func
def original(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [list(x) for x in itertools.combinations(r, i) if sum(list(x)) == val]
    return res

@simple_time_func
def improved0(val, r):
    res = list()
    for i in range(len(r) + 1):
        res += [x for x in itertools.combinations(r, i) if sum(x) == val]
    return res


for val in range(21, 28):
    r = range(val)[1:]
    print("\nval: {}".format(val))
    for func in (original, improved0):
        res = func(val, r)
        #print("    Solution : %s " % res)
        #print("    Combinations : %s" % len(res))

备注

  • 我拿了昂贵的部分(for循环)并将其封装在一个函数(original)中以便计时
  • 我将改进的循环放在另一个函数中(称为improved0
  • 其余代码(不幸的是,其中大部分代码)仅用于性能测试

<强>输出

(py35x64_test) c:\Work\Dev\StackOverflow\q46853086>"c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" a.py

val: 21
original took 0.573 seconds.
improved0 took 0.325 seconds.

val: 22
original took 1.185 seconds.
improved0 took 0.633 seconds.

val: 23
original took 2.388 seconds.
improved0 took 1.300 seconds.

val: 24
original took 4.880 seconds.
improved0 took 2.609 seconds.

val: 25
original took 9.796 seconds.
improved0 took 5.243 seconds.

val: 26
original took 19.701 seconds.
improved0 took 10.489 seconds.

val: 27
original took 39.314 seconds.
improved0 took 21.559 seconds.

正如输出显示的那样,这种明显微不足道的变化几乎将时间缩短了一半 下一步包括真实优化(因为计算复杂性仍然看起来是指数级的),关于数学和编程技巧的有效使用,更进一步提高速度(不幸的是我已经没时间了)