问题描述
所以基本上我有一个包含 50 个覆盖率的文本文件,从数字 0 开始大约波动(加减)1*10^{-6}。我试图从数据集中找到 10 个数字,这给了我最接近数字 0 的数字之和。 有没有办法在 python 中通过迭代所有数字并从 50 个数字中找到 10 个数字来做到这一点给我最接近零的数字?希望这个问题有意义:/
解决方法
使用 itertools.combinations
,应该不到一个小时:
min(combinations(numbers,10),key=lambda c: abs(sum(c)))
更快的想法:将数字分成两组 A 和 B,每组 25 个数字。取 A 中的 i 个数字和 B 中的 10-i 个数字(尝试从 0 到 10 的所有 i)。
例如,当从 A 中取出 3 个数字和从 B 中取出 7 个数字时,A 中有 25C3=2300 种组合,B 中有 25C7=480700 种组合。将 B 中的组合按总和排序,然后遍历 A 中的组合并对其进行二分查找求和 B 中的组合求和,找到 B 中的最佳组合与 A 中的组合相结合。
对于 i>5,即,当您从 A 中获取的数字多于从 B 中获取的数字,因此从 A 中获取的组合多于从 B 中获取的组合,请对来自 A 的数字进行排序,然后对来自 B 的数字进行排序,并在来自 A 的数字中进行二分查找。
每个组合需要更多的努力,但总体而言组合要少得多,所以我认为它会更快:
>>> from math import comb
>>> comb(50,10)
10272278170
>>> sum(comb(25,i) + comb(25,10-i) for i in range(11))
14239032
>>> 10272278170 / 14239032
721.4168891537009
带有附加总和的组合的创建和排序应该花费大部分时间。为 i
from random import random
from itertools import combinations
numbers = [random() * 2e-6 - 1e-6 for _ in range(50)]
B = numbers[25:]
for i in range(6):
combs = [(sum(comb),comb) for comb in combinations(B,10-i)]
combs.sort()
总的来说,我认为这个解决方案大约需要一分钟。
或者我们可以先找到最好的和,然后在最后重建产生那个和的组合。以下大约需要 4 秒,因此整个真正的解决方案可能需要大约 10 秒:
for i in range(6):
sums = list(map(sum,combinations(B,10-i)))
sums.sort()