[英]Calculate the number of combinations of unique positive integers with minimum and maximum differences between each other?
How do I write a Python program to calculate the number of combinations of unique sorted positive integers over a range of integers that can be selected where the minimum difference between each of the numbers in the set is one number and the maximum difference is another number? 我如何编写Python程序来计算在整数范围内唯一排序的正整数组合的数量,该整数范围内集合中每个数字之间的最小差是一个数字而最大差是另一个数字?
For instance, if I want to calculate the number of ways I can select 6 numbers from the positive integers from 1-50 such that the minimum difference between each number is 4 and the maximum difference between each number is 7, I would want to count the combination {1,6,12,18,24,28} since the minimum difference is 4 and the maximum difference is 6, but I would not want to count combinations like {7,19,21,29,41,49} since the minimum difference is 2 and the maximum difference is 12. 例如,如果我想计算可以从1-50的正整数中选择6个数字的方式,以使每个数字之间的最小差为4,而每个数字之间的最大差为7,则我想计算组合{1,6,12,18,24,28},因为最小差异为4,最大差异为6,但我不想计算类似{7,19,21,29,41,49}的组合因为最小差异为2,最大差异为12。
I have the following code so far, but the problem is that it has to loop through every combination, which takes an extremely long time in many cases. 到目前为止,我有以下代码,但问题是它必须遍历每个组合,在许多情况下这要花费很长时间。
import itertools
def min_max_differences(integer_list):
i = 1
diff_min = max(integer_list)
diff_max = 1
while i < len(integer_list):
diff = (integer_list[i]-integer_list[i-1])
if diff < diff_min:
diff_min = diff
if diff > diff_max:
diff_max = diff
i += 1
return (diff_min,diff_max)
def total_combinations(lower_bound,upper_bound,min_difference,max_difference,elements_selected):
numbers_range = list(range(lower_bound,upper_bound+1,1))
all_combos = itertools.combinations(numbers_range,elements_selected)
min_max_diff_combos = 0
for c in all_combos:
if min_max_differences(c)[0] >= min_difference and min_max_differences(c)[1] <= max_difference:
min_max_diff_combos += 1
return min_max_diff_combos
I do not have a background in combinatorics, but I am guessing there is a much more algorithmically efficient way to do this using some combinatorial methods. 我没有组合技术的背景知识,但是我猜想有一种使用某些组合方法在算法上更有效的方法。
You can use a recursive function with caching to get your answer. 您可以将递归函数与缓存一起使用来获取答案。 This method will work even if you have a large array because some positions are repeated many times with the same parameters.
即使您的数组很大,此方法也将起作用,因为使用相同的参数将某些位置重复多次。
Here is a code for you (forgive me if I made any mistakes in python cause I don't normally use it). 这是给您的代码(如果我在python中犯了任何错误,请原谅我,因为我通常不使用它)。 If there is any flow in the logic, please let me know
如果逻辑上有任何流程,请告诉我
# function to get the number of ways to select {target} numbers from the
# array {numbers} with minimum difference {min} and maximum difference {max}
# starting from position {p}, with the help of caching
dict = {}
def Combinations(numbers, target, min, max, p):
if target == 1: return 1
# get a unique key for this position
key = target * 1000000000000 + min * 100000000 + max * 10000 + p
if dict.has_key(key): return dict[key]
ans = 0
# current start value
pivot = numbers[p]
p += 1;
# increase the position until you reach the minimum
while p < len(numbers) and numbers[p] - pivot < min:
p += 1
# get all the values in the range of min <--> max
while p < len(numbers) and numbers[p] - pivot <= max:
ans += Combinations(numbers, target - 1, min, max, p)
p += 1
# store the ans for further inquiry
dict[key] = ans
return ans
# any range of numbers (must be SORTED as you asked)
numbers = []
for i in range(0,50): numbers.append(i+1)
# number of numbers to select
count = 6
# minimum difference
min = 4
# maximum difference
max = 7
ans = 0
for i in range(0,len(numbers)):
ans += Combinations(numbers, count, min, max, i)
print ans
Here is a very simple (and non-optimized) recursive approach: 这是一种非常简单(且未优化)的递归方法:
import numpy as np
from time import time
""" PARAMETERS """
SET = range(50) # Set of elements to choose from
N = 6 # N elements to choose
MIN_GAP = 4 # Gaps
MAX_GAP = 7 # ""
def count(N, CHOSEN=[]):
""" assumption: N > 0 at start """
if N == 0:
return 1
else:
return sum([count(N-1, CHOSEN + [val])
for val in SET if (val not in CHOSEN)
and ((not CHOSEN) or ((val - CHOSEN[-1]) >= MIN_GAP))
and ((not CHOSEN) or ((val - CHOSEN[-1]) <= MAX_GAP))])
start_time = time()
count_ = count(N)
print('used time in secs: ', time() - start_time)
print('# solutions: ', count_)
('used time in secs: ', 0.1174919605255127)
('# solutions: ', 23040)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.