簡體   English   中英

計算具有最小和最大差異的唯一正整數的組合數量?

[英]Calculate the number of combinations of unique positive integers with minimum and maximum differences between each other?

我如何編寫Python程序來計算在整數范圍內唯一排序的正整數組合的數量,該整數范圍內集合中每個數字之間的最小差是一個數字而最大差是另一個數字?

例如,如果我想計算可以從1-50的正整數中選擇6個數字的方式,以使每個數字之間的最小差為4,而每個數字之間的最大差為7,則我想計算組合{1,6,12,18,24,28},因為最小差異為4,最大差異為6,但我不想計算類似{7,19,21,29,41,49}的組合因為最小差異為2,最大差異為12。

到目前為止,我有以下代碼,但問題是它必須遍歷每個組合,在許多情況下這要花費很長時間。

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

我沒有組合技術的背景知識,但是我猜想有一種使用某些組合方法在算法上更有效的方法。

您可以將遞歸函數與緩存一起使用來獲取答案。 即使您的數組很大,此方法也將起作用,因為使用相同的參數將某些位置重復多次。
這是給您的代碼(如果我在python中犯了任何錯誤,請原諒我,因為我通常不使用它)。 如果邏輯上有任何流程,請告訴我

# 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

這是一種非常簡單(且未優化)的遞歸方法:

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)

備注

  • 它輸出與Ayman方法相同的解決方案
  • 艾曼(Ayman)的方法更強大(就漸近速度而言)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM