【问题标题】:Calculating all possible combinations for binomial coefficients in Python?在 Python 中计算二项式系数的所有可能组合?
【发布时间】:2020-05-12 05:57:02
【问题描述】:

我有一个包含大约 120 个项目的列表,我需要检查一半列表的每个可能的不同组合,即 60 个项目,其中顺序无关紧要。所以这些组合的数量应该是 120!/(60!*60!)。问题是,我需要检查每个组合,因为我想为某个问题找到“最佳”组合。有谁知道如何解决这个问题?

(如果你有兴趣,我的问题如下: 在我的学校,有一半的人这周上学,其他人下周,然后我们这周又上学,等等。问题是,这是随机分配的,所以有些班级的学生人数不成比例(班级每个 25 人,所以一个班级在第 1 周有 19 名学生,在第 2 周有 6 名学生)。所以,我想找到最好的方法来划分学生,我们总共大约有 120 人,这样每个班级的人数大约是原来的一半。我的想法是为每个班级和他们的学生制作一个列表,并检查每个总数的组合的比例,从每个班级的比例中减去 0.5,然后将每个班级的差值的绝对值相加。总和最小的组合是最好的,因为类是最均匀的。)

【问题讨论】:

  • itertools 模块中有一个方法可以枚举组合。但是,有 96614908840363322603893139521372656 这样的组合......你将不得不找到另一种方法。首先,更准确地描述您的问题,因为它很不清楚。
  • 是的,scipy.special.binom(120,60) 有 119 个二进制数字。这就像接近“太阳系中的原子数”之类的东西。这意味着即使您是 2 型文明,您也可能无法遍历所有组合。
  • 如果您能很多更具体地了解“最佳”对学生的划分意味着什么以及您所说的“比例”等等等等。然后有可能想出一个更聪明的方法来解决这个问题。但无论如何,您目前似乎并没有真正的编程问题,而是一般的解决问题的问题。

标签: python combinations


【解决方案1】:

下面的函数将返回列表中所有可能的项目组合,而每个组合将包含列表长度(即 120)的项目:

from itertools import product

def algorithm(myList):
    possible = [''.join(combination) for combination in product(myList, repeat= len(myList))]
    return possible
print(algorithm(myList))

请注意,上面的函数只允许长度等于您的列表长度的组合,如果您想允许低于 120 的其他组合,下面应该这样做:

def algorithm(myList):
    allPoss = list()
    for i in range(1, len(myList)+1):
        possible = [''.join(combination) for combination in product(myList, repeat= i)]
        allPoss.append(possible)
    return allPoss
print(algorithm(myList))

你提到你想做一半的事情:

一半列表的组合,所以 60 项

现在我不确定你的意思是什么?

1- 你有特定的 60 个项目想要组合吗?然后为这 60 个项目创建一个子列表并运行上述函数。

2- 你希望组合只有 60 个项目吗?使用第一个函数但传递repeat = 60

3- 还有其他可能的解释吗?告诉我!

我是不是完全误解了你的问题,我的回答毫无意义?抱歉,再解释一遍!

编辑: 我刚刚意识到上述功能允许在组合中重复项目,如果您不想允许,您可以尝试类似这样的操作,如果您只需要 60,您可以再次将 range(0,len(vals) 调整为 60长度组合或 range(0,(len(vals)/2) 以允许低于 60 的其他组合:

import itertools

def generate(vals):
    return ("".join(x) for x in itertools.chain.from_iterable(itertools.permutations(vals,i+1) for i in range(0,len(vals))))
print(list(generate("".join(myList))))

第二次编辑:这应该可以解决问题:

import itertools

def generate(vals):
    return ("".join(x) for x in itertools.chain.from_iterable(itertools.permutations(vals,i+1) for i in range(0,60)))
combinations = list(generate("".join(myList)))

#to keep those of 60 length:
result = [item for item in combinations if len(item)==60]

【讨论】:

  • 很抱歉没有澄清,是的,我的意思是每个组合应该只有 60 项,或者是原始列表长度的一半。所以对于列表 [1,2,3,4],组合将是 [1,2],[1,3],[1,4],[2,3],[2,4],[3 ,4]
  • 我已经根据我的理解更新了第二次编辑的答案,试试这个,看看是不是你想要的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
  • 2015-11-10
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多