2016-12-15 11 views
-1

N個の要素をAボックスに配置する方法をすべて見つけようとしています。ボックスの順序と要素の順序は関係ありませんが、どの要素が同じボックスにあるかは関係ありません。例えば、3ボックスと3つの要素のために期待される結果は怒鳴るです:私はすべての貢献のために非常に感謝されるEnumeration of combinations of N balls in A boxes?並べ替えAボックス内のN個の要素は?

  box_1  box_2  box_3 
case-1  [1,2,3] []   [] 
case-2  [1,2]  [3]   [] 
case-3  [1,3]  [2]   [] 
case-4  [2,3]  [1]   [] 
case-5  [1]  [2]   [3] 

これがここで尋ねたものよりも似ていますが、より多くの一般的な問題であり、この質問には、好ましくはPython言語を使用します。

答えて

0

これらは、set partitionsと呼ばれます。再帰関数はSet partitions in Pythonにあります。もう少し効率的な「ボトムアップ」再帰バージョンはこれです:

def generate_partitions(a): 
    a = list(a) 
    n = len(a) 
    partition = [] # a list of lists, currently empty 

    def assign(i): 
     if i >= n: 
      yield [list(part) for part in partition] 
     else: 
      # assign a[i] to an existing part 
      for part in partition: 
       part.append(a[i]) 
       yield from assign(i + 1) 
       part.pop() 

      # assign a[i] to a completely new part 
      partition.append([a[i]]) 
      yield from assign(i + 1) 
      partition.pop() 

    if n: 
     yield from assign(0) 
    else: 
     yield [[]] 


for partition in generate_partitions([1,2,3]): 
    print(*partition) 

出力:

[1, 2, 3] 
[1, 2] [3] 
[1, 3] [2] 
[1] [2, 3] 
[1] [2] [3] 

これはあなたの例のように、空のボックスを生成しませんが、それは些細に発電機を補強するためにそうする。

反復アルゴリズムについては、Michael Orlov(2002)の "Set Partitionの効率的な生成"を参照してください。設定されたパーティションの数は、にすばやく増えます。したがって、反復アルゴリズムでさえ、適度なサイズのセットのすべてのパーティションを列挙するのに時間がかかることに注意してください。

カウント生成されていない設定パーティションの数は、Bell Numbers(OEIS A000110)を参照してください。 PythonでBell番号を計算するには、次のような手順があります(効率的ではありません):

def bell(n): 
    "-> the n'th Bell number." 
    assert n >= 0, n 

    # loop will execute at least once 
    for b in bell_sequence(n): 
     pass 

    return b 

def bell_sequence(n): 
    """Yields the Bell numbers b(0),b(1)...b(n). 

    This function requires O(n) auxiliary storage. 
    """ 
    assert n >= 0, n 
    # compute Bell numbers using the triangle scheme 
    yield 1 # b(0) 

    row = [1] + (n-1)*[0] 

    for i in range(0, n): 
     row[i] = row[0] 

     for k in reversed(range(i)): 
      row[k] += row[k + 1] 

     yield row[0] # b(i + 1) 
関連する問題