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)
注意:deepcopy functionality
计算效率 HACK
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)