[英]Numpy: given a set of ranges, is there an efficient way to find the set of ranges that are disjoint with all other ranges?
[英]Given a list of ranges, find all combination for these ranges that sums upto k
我有 34 个数字范围。 例如:
x1 = {25,35}
x2 = {28,36}
x3 = {15,20}
.
.
x34 = {28,37}
我必须找到所有组合,以便我从每个范围中选择一个数字,并且所有这 34 个数字总和为 k。
例如:
let k = 600
so from x1 - we pick 26
from x2 - we pick 29
.
.
and from x34 we pick 16.
Then, x1 + x2 + x3 + x4 + … + x34 = 600.
我想要所有这样的组合。
用某种算法可行吗?
我想在 python 中实现这个。
range(a, b)
a 包括在内, b 不包括在内。 所以这里的实际范围是:
{20, 25}
{30, 36}
{10, 39}
all_ranges = [range(20, 26), range(30, 37), range(10, 40)]
def get_combinations(ranges, k):
if ranges.__len__() == 0:
return int(k == 0)
combinations = 0
for i in ranges[0]:
# if k - i < 0:
# break
combinations += get_combinations(ranges[1:], k - i)
return combinations
print(get_combinations(all_ranges, 70))
我们不会将数字相加直到达到k
,而是从k
中减去直到达到零。
if ranges.__len__() == 0:
return int(k == 0)
这是终止递归的块。 基本上,如果我们从k
中减去从范围中选择的每个数字,那么结果必须为零。
combinations = 0
for i in ranges[0]:
combinations += get_combinations(ranges[1:], k - i)
请注意,注释的部分仅用于提高效率。 所以我们在这里选择一个数字,我们最初选择它是k
。 然后我们遍历第一个范围的所有值,并获得新的k - i
与新的范围ranges[1:]
的组合。 你可以看到这些东西是如何结合在一起的。
请原谅我,我没有注意到 OP 本身需要这些组合。 尽管如此,我还是将上面的代码留给未来的访问者。
使用与上述相同的逻辑,我们可以得到二维列表中的所有组合。
from copy import deepcopy
all_ranges = [range(20, 26), range(30, 37), range(10, 40)]
def get_combinations(ranges, k, initial_combination=None):
if not initial_combination:
initial_combination = []
combinations = []
if ranges.__len__() == 1:
for i in ranges[0]:
if k - i < 0:
return combinations
elif k - i == 0:
_ = deepcopy(initial_combination)
_.append(i)
combinations.append(_)
return combinations
for i in ranges[0]:
_ = deepcopy(initial_combination)
_.append(i)
combinations += get_combinations(ranges[1:], k - i, _)
return combinations
get_combinations(all_ranges, 70)
注意: 深拷贝功能
from copy import deepcopy
all_ranges = [range(10, 40), range(20, 30), range(40, 50)]
def get_minimums():
m = []
for index, r in enumerate(all_ranges):
m.append(sum([_.start for _ in all_ranges[index + 1:]]))
minimums = get_minimums() #[60, 40, 0]
def get_combinations(ranges, k, initial_combination=None):
if not initial_combination:
initial_combination = []
combinations = []
if ranges.__len__() == 1:
for i in ranges[0]:
if k - i < 0:
break
elif k - i == 0:
_ = deepcopy(initial_combination)
_.append(i)
print(_)
combinations.append(_)
return combinations
minimum = minimums[-ranges.__len__()]
for i in range(ranges[0].start, ranges[0].stop):
if k - minimum - i < 0:
break
_ = deepcopy(initial_combination)
_.append(i)
combinations += get_combinations(ranges[1:], k - i, _)
return combinations
get_combinations(all_ranges, 90)
您可以使用 itertools 的产品方法来检查 n 个 arrays 之间的所有组合。
例如:
import itertools
a = [1,2]
b = ['a' , 'b']
c = list(itertools.product(a,b))
>> [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
因此,如果您想知道构成给定数字的所有组合,您只需在最终列表中进行迭代并检查所有结果。
import itertools
x1 = range(25,35)
x2 = range(28,36)
x3 = range(15,20)
result = []
for item in list(itertools.product(x1,x2,x3)):
if sum(item) == 75:
result.append(item)
print(result)
>> [(25, 31, 19), (25, 32, 18), (25, 33, 17), (25, 34, 16), .....]
如果您以前不知道范围数,您只需在 itertools.product 中使用 * 运算符,代码将相同
ranges = [range(1,5), range(5,29), range(3, 400), ...]
#STUFF
itertools.product(*ranges)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.