将彩球放入箱子的所有可能方法

All possible ways to place colored balls into bins

我有很多垃圾箱。每个箱子只能容纳一个球。

比方说,我有

Na 个红球

Nb个蓝球

Nc绿球数

等等。

我想找出将球放入长度为 (Na+Nb+Nc) 的容器中的所有可能方法。

例如,假设我只有两个红球和两个蓝球。我想将它们放入 4 个箱子中。可能的排列方式有:

R R B B
R B R B
R B B R
B R R B
B R B R
B B R R

(希望没有漏掉任何一个组合)

有什么简单的方法可以为不同的颜色生成索引,例如:

First row is : R=(0,1) B=(2,3)
Second row is : R=(0,2) B=(1,3)

有没有一种简单的方法可以在 numpy 中生成它?

垃圾箱实际上有不同的重量,例如:

[0.1, 0.3, 0.2, 0.5]

因此,对于表示为 R at (0,1) and B at (2,3) 的组合 R R B B ,R 的总权重为 0.1+0.3=0.4,B 的总权重为 0.2+0.5=0.7

我最终对不同排列中每种颜色的总权重感兴趣,并想从另一个成本函数 f(total_weight(R), total_weight(B) 中选择最好的一个).如果总重量的生成可以在 numpy 中以不同的简单方式完成,有什么意见吗?

生成排列并删除重复项。

>>> import itertools
>>> Na = 2
>>> Nb = 2
>>> p = itertools.permutations(['R']*Na + ['B']*Nb)
>>> for perm in sorted(list(set(p)), reverse=True):
...     print perm
... 
('R', 'R', 'B', 'B')
('R', 'B', 'R', 'B')
('R', 'B', 'B', 'R')
('B', 'R', 'R', 'B')
('B', 'R', 'B', 'R')
('B', 'B', 'R', 'R')

你可以用 itertools 解决这个问题:

import itertools
last = None
result = []
for v in itertools.permutations(['A','A','B','B']):
    key = "".join(v)
    if key == last: continue
    last = key
    result.append(v)
print result

这是一个不需要消除重复排列的 "multi-combinations" 实现。第一个参数 n 是列表 [Na, Nb, Nc, ...]。

它是作为递归生成器实现的,因此您可以遍历组合,而无需一次将它们全部存储在内存中。您在评论中说 Na + Nb + ... 通常在 20 左右,但可能高达 50 或 100。这意味着您几乎肯定不想将所有组合存储在内存中。考虑一个有四个 "colors" 的例子,其中 Na = Nb = Nc = Nd = 5。组合的数量是 choose(20, 5) * choose(15, 5) * choose(10, 5) = 11732745024,其中 choose(n, k)binomial coefficient。我的计算机只有 16 GB 的 RAM,因此组合数量所需的存储空间将远远超过我计算机的内存。

from itertools import combinations


def multicombinations(n, bins=None):
    if bins is None:
        bins = set(range(sum(n)))
    if len(n) == 0:
        yield []
    else:
        for c in combinations(bins, n[0]):
            for t in multicombinations(n[1:], bins - set(c)):
                yield [c] + t

它生成一个元组列表。也就是说,如果您对第一行的描述是 "First row is : R=(0,1) B=(2,3)",则 multicombinations([2, 2]) 生成的第一个值是 [(0, 1), (2, 3)]。 (考虑到您接下来要进行的权重计算的描述,这可能不是结果的最佳格式。)

一些例子:

In [74]: list(multicombinations([2, 2]))
Out[74]: 
[[(0, 1), (2, 3)],
 [(0, 2), (1, 3)],
 [(0, 3), (1, 2)],
 [(1, 2), (0, 3)],
 [(1, 3), (0, 2)],
 [(2, 3), (0, 1)]]

In [75]: list(multicombinations([3, 2]))
Out[75]: 
[[(0, 1, 2), (3, 4)],
 [(0, 1, 3), (2, 4)],
 [(0, 1, 4), (2, 3)],
 [(0, 2, 3), (1, 4)],
 [(0, 2, 4), (1, 3)],
 [(0, 3, 4), (1, 2)],
 [(1, 2, 3), (0, 4)],
 [(1, 2, 4), (0, 3)],
 [(1, 3, 4), (0, 2)],
 [(2, 3, 4), (0, 1)]]

In [76]: list(multicombinations([2, 3, 2]))
Out[76]: 
[[(0, 1), (2, 3, 4), (5, 6)],
 [(0, 1), (2, 3, 5), (4, 6)],
 [(0, 1), (2, 3, 6), (4, 5)],
 [(0, 1), (2, 4, 5), (3, 6)],
 [(0, 1), (2, 4, 6), (3, 5)],
 [(0, 1), (2, 5, 6), (3, 4)],
 [(0, 1), (3, 4, 5), (2, 6)],
 [(0, 1), (3, 4, 6), (2, 5)],
 [(0, 1), (3, 5, 6), (2, 4)],
 [(0, 1), (4, 5, 6), (2, 3)],
 [(0, 2), (1, 3, 4), (5, 6)],
 [(0, 2), (1, 3, 5), (4, 6)],
 [(0, 2), (1, 3, 6), (4, 5)],
 [(0, 2), (1, 4, 5), (3, 6)],
 [(0, 2), (1, 4, 6), (3, 5)],
 [(0, 2), (1, 5, 6), (3, 4)],
 [(0, 2), (3, 4, 5), (1, 6)],
 [(0, 2), (3, 4, 6), (1, 5)],
 [(0, 2), (3, 5, 6), (1, 4)],
 [(0, 2), (4, 5, 6), (1, 3)],
 [(0, 3), (1, 2, 4), (5, 6)],
 [(0, 3), (1, 2, 5), (4, 6)],
 [(0, 3), (1, 2, 6), (4, 5)],
 [(0, 3), (1, 4, 5), (2, 6)],
 [(0, 3), (1, 4, 6), (2, 5)],
 [(0, 3), (1, 5, 6), (2, 4)],
 [(0, 3), (2, 4, 5), (1, 6)],
 [(0, 3), (2, 4, 6), (1, 5)],
 [(0, 3), (2, 5, 6), (1, 4)],
 [(0, 3), (4, 5, 6), (1, 2)],
 [(0, 4), (1, 2, 3), (5, 6)],
 [(0, 4), (1, 2, 5), (3, 6)],
 [(0, 4), (1, 2, 6), (3, 5)],
 [(0, 4), (1, 3, 5), (2, 6)],
 [(0, 4), (1, 3, 6), (2, 5)],
 [(0, 4), (1, 5, 6), (2, 3)],
 [(0, 4), (2, 3, 5), (1, 6)],
 [(0, 4), (2, 3, 6), (1, 5)],
 [(0, 4), (2, 5, 6), (1, 3)],
 [(0, 4), (3, 5, 6), (1, 2)],
 [(0, 5), (1, 2, 3), (4, 6)],
 [(0, 5), (1, 2, 4), (3, 6)],
 [(0, 5), (1, 2, 6), (3, 4)],
 [(0, 5), (1, 3, 4), (2, 6)],
 [(0, 5), (1, 3, 6), (2, 4)],
 [(0, 5), (1, 4, 6), (2, 3)],
 [(0, 5), (2, 3, 4), (1, 6)],
 [(0, 5), (2, 3, 6), (1, 4)],
 [(0, 5), (2, 4, 6), (1, 3)],
 [(0, 5), (3, 4, 6), (1, 2)],
 [(0, 6), (1, 2, 3), (4, 5)],
 [(0, 6), (1, 2, 4), (3, 5)],
 [(0, 6), (1, 2, 5), (3, 4)],
 [(0, 6), (1, 3, 4), (2, 5)],
 [(0, 6), (1, 3, 5), (2, 4)],
 [(0, 6), (1, 4, 5), (2, 3)],
 [(0, 6), (2, 3, 4), (1, 5)],
 [(0, 6), (2, 3, 5), (1, 4)],
 [(0, 6), (2, 4, 5), (1, 3)],
 [(0, 6), (3, 4, 5), (1, 2)],
 [(1, 2), (0, 3, 4), (5, 6)],
 [(1, 2), (0, 3, 5), (4, 6)],
 [(1, 2), (0, 3, 6), (4, 5)],
 [(1, 2), (0, 4, 5), (3, 6)],
 [(1, 2), (0, 4, 6), (3, 5)],
 [(1, 2), (0, 5, 6), (3, 4)],
 [(1, 2), (3, 4, 5), (0, 6)],
 [(1, 2), (3, 4, 6), (0, 5)],
 [(1, 2), (3, 5, 6), (0, 4)],
 [(1, 2), (4, 5, 6), (0, 3)],
 [(1, 3), (0, 2, 4), (5, 6)],
 [(1, 3), (0, 2, 5), (4, 6)],
 [(1, 3), (0, 2, 6), (4, 5)],
 [(1, 3), (0, 4, 5), (2, 6)],
 [(1, 3), (0, 4, 6), (2, 5)],
 [(1, 3), (0, 5, 6), (2, 4)],
 [(1, 3), (2, 4, 5), (0, 6)],
 [(1, 3), (2, 4, 6), (0, 5)],
 [(1, 3), (2, 5, 6), (0, 4)],
 [(1, 3), (4, 5, 6), (0, 2)],
 [(1, 4), (0, 2, 3), (5, 6)],
 [(1, 4), (0, 2, 5), (3, 6)],
 [(1, 4), (0, 2, 6), (3, 5)],
 [(1, 4), (0, 3, 5), (2, 6)],
 [(1, 4), (0, 3, 6), (2, 5)],
 [(1, 4), (0, 5, 6), (2, 3)],
 [(1, 4), (2, 3, 5), (0, 6)],
 [(1, 4), (2, 3, 6), (0, 5)],
 [(1, 4), (2, 5, 6), (0, 3)],
 [(1, 4), (3, 5, 6), (0, 2)],
 [(1, 5), (0, 2, 3), (4, 6)],
 [(1, 5), (0, 2, 4), (3, 6)],
 [(1, 5), (0, 2, 6), (3, 4)],
 [(1, 5), (0, 3, 4), (2, 6)],
 [(1, 5), (0, 3, 6), (2, 4)],
 [(1, 5), (0, 4, 6), (2, 3)],
 [(1, 5), (2, 3, 4), (0, 6)],
 [(1, 5), (2, 3, 6), (0, 4)],
 [(1, 5), (2, 4, 6), (0, 3)],
 [(1, 5), (3, 4, 6), (0, 2)],
 [(1, 6), (0, 2, 3), (4, 5)],
 [(1, 6), (0, 2, 4), (3, 5)],
 [(1, 6), (0, 2, 5), (3, 4)],
 [(1, 6), (0, 3, 4), (2, 5)],
 [(1, 6), (0, 3, 5), (2, 4)],
 [(1, 6), (0, 4, 5), (2, 3)],
 [(1, 6), (2, 3, 4), (0, 5)],
 [(1, 6), (2, 3, 5), (0, 4)],
 [(1, 6), (2, 4, 5), (0, 3)],
 [(1, 6), (3, 4, 5), (0, 2)],
 [(2, 3), (0, 1, 4), (5, 6)],
 [(2, 3), (0, 1, 5), (4, 6)],
 [(2, 3), (0, 1, 6), (4, 5)],
 [(2, 3), (0, 4, 5), (1, 6)],
 [(2, 3), (0, 4, 6), (1, 5)],
 [(2, 3), (0, 5, 6), (1, 4)],
 [(2, 3), (1, 4, 5), (0, 6)],
 [(2, 3), (1, 4, 6), (0, 5)],
 [(2, 3), (1, 5, 6), (0, 4)],
 [(2, 3), (4, 5, 6), (0, 1)],
 [(2, 4), (0, 1, 3), (5, 6)],
 [(2, 4), (0, 1, 5), (3, 6)],
 [(2, 4), (0, 1, 6), (3, 5)],
 [(2, 4), (0, 3, 5), (1, 6)],
 [(2, 4), (0, 3, 6), (1, 5)],
 [(2, 4), (0, 5, 6), (1, 3)],
 [(2, 4), (1, 3, 5), (0, 6)],
 [(2, 4), (1, 3, 6), (0, 5)],
 [(2, 4), (1, 5, 6), (0, 3)],
 [(2, 4), (3, 5, 6), (0, 1)],
 [(2, 5), (0, 1, 3), (4, 6)],
 [(2, 5), (0, 1, 4), (3, 6)],
 [(2, 5), (0, 1, 6), (3, 4)],
 [(2, 5), (0, 3, 4), (1, 6)],
 [(2, 5), (0, 3, 6), (1, 4)],
 [(2, 5), (0, 4, 6), (1, 3)],
 [(2, 5), (1, 3, 4), (0, 6)],
 [(2, 5), (1, 3, 6), (0, 4)],
 [(2, 5), (1, 4, 6), (0, 3)],
 [(2, 5), (3, 4, 6), (0, 1)],
 [(2, 6), (0, 1, 3), (4, 5)],
 [(2, 6), (0, 1, 4), (3, 5)],
 [(2, 6), (0, 1, 5), (3, 4)],
 [(2, 6), (0, 3, 4), (1, 5)],
 [(2, 6), (0, 3, 5), (1, 4)],
 [(2, 6), (0, 4, 5), (1, 3)],
 [(2, 6), (1, 3, 4), (0, 5)],
 [(2, 6), (1, 3, 5), (0, 4)],
 [(2, 6), (1, 4, 5), (0, 3)],
 [(2, 6), (3, 4, 5), (0, 1)],
 [(3, 4), (0, 1, 2), (5, 6)],
 [(3, 4), (0, 1, 5), (2, 6)],
 [(3, 4), (0, 1, 6), (2, 5)],
 [(3, 4), (0, 2, 5), (1, 6)],
 [(3, 4), (0, 2, 6), (1, 5)],
 [(3, 4), (0, 5, 6), (1, 2)],
 [(3, 4), (1, 2, 5), (0, 6)],
 [(3, 4), (1, 2, 6), (0, 5)],
 [(3, 4), (1, 5, 6), (0, 2)],
 [(3, 4), (2, 5, 6), (0, 1)],
 [(3, 5), (0, 1, 2), (4, 6)],
 [(3, 5), (0, 1, 4), (2, 6)],
 [(3, 5), (0, 1, 6), (2, 4)],
 [(3, 5), (0, 2, 4), (1, 6)],
 [(3, 5), (0, 2, 6), (1, 4)],
 [(3, 5), (0, 4, 6), (1, 2)],
 [(3, 5), (1, 2, 4), (0, 6)],
 [(3, 5), (1, 2, 6), (0, 4)],
 [(3, 5), (1, 4, 6), (0, 2)],
 [(3, 5), (2, 4, 6), (0, 1)],
 [(3, 6), (0, 1, 2), (4, 5)],
 [(3, 6), (0, 1, 4), (2, 5)],
 [(3, 6), (0, 1, 5), (2, 4)],
 [(3, 6), (0, 2, 4), (1, 5)],
 [(3, 6), (0, 2, 5), (1, 4)],
 [(3, 6), (0, 4, 5), (1, 2)],
 [(3, 6), (1, 2, 4), (0, 5)],
 [(3, 6), (1, 2, 5), (0, 4)],
 [(3, 6), (1, 4, 5), (0, 2)],
 [(3, 6), (2, 4, 5), (0, 1)],
 [(4, 5), (0, 1, 2), (3, 6)],
 [(4, 5), (0, 1, 3), (2, 6)],
 [(4, 5), (0, 1, 6), (2, 3)],
 [(4, 5), (0, 2, 3), (1, 6)],
 [(4, 5), (0, 2, 6), (1, 3)],
 [(4, 5), (0, 3, 6), (1, 2)],
 [(4, 5), (1, 2, 3), (0, 6)],
 [(4, 5), (1, 2, 6), (0, 3)],
 [(4, 5), (1, 3, 6), (0, 2)],
 [(4, 5), (2, 3, 6), (0, 1)],
 [(4, 6), (0, 1, 2), (3, 5)],
 [(4, 6), (0, 1, 3), (2, 5)],
 [(4, 6), (0, 1, 5), (2, 3)],
 [(4, 6), (0, 2, 3), (1, 5)],
 [(4, 6), (0, 2, 5), (1, 3)],
 [(4, 6), (0, 3, 5), (1, 2)],
 [(4, 6), (1, 2, 3), (0, 5)],
 [(4, 6), (1, 2, 5), (0, 3)],
 [(4, 6), (1, 3, 5), (0, 2)],
 [(4, 6), (2, 3, 5), (0, 1)],
 [(5, 6), (0, 1, 2), (3, 4)],
 [(5, 6), (0, 1, 3), (2, 4)],
 [(5, 6), (0, 1, 4), (2, 3)],
 [(5, 6), (0, 2, 3), (1, 4)],
 [(5, 6), (0, 2, 4), (1, 3)],
 [(5, 6), (0, 3, 4), (1, 2)],
 [(5, 6), (1, 2, 3), (0, 4)],
 [(5, 6), (1, 2, 4), (0, 3)],
 [(5, 6), (1, 3, 4), (0, 2)],
 [(5, 6), (2, 3, 4), (0, 1)]]

这是一种可能的实施方式:

def permutations(colors, l):
    if l == 0:
        yield []
    else:
        for i in range(len(colors)):
            if colors[i]:
                la = colors[:i]
                lb = [colors[i][1:]]
                lc = colors[i + 1:]
                choice = colors[i][0]
                for rest in permutations(la + lb + lc, l - 1):
                    yield [choice] + rest

用法:

for choice in permutations([['R'] * 2, ['B'] * 2], 4):
    print(choice)


['R', 'R', 'B', 'B']
['R', 'B', 'R', 'B']
['R', 'B', 'B', 'R']
['B', 'R', 'R', 'B']
['B', 'R', 'B', 'R']
['B', 'B', 'R', 'R']