Algorithm 桶置换算法

Algorithm 桶置换算法,algorithm,permutation,Algorithm,Permutation,我正在寻找一个这样的算法 permutateBuckets([A,B,C]) 并给出以下结果: [ [[A,B,C]], [[A,B],[C]], [[A,C],[B]], [[B,C],[A]], [[A],[B,C]], [[B],[A,C]], [[C],[A,B]], [[A],[B],[C]], [[A],[C],[B]], [[B],[A],[C]], [[B],[C],[A]], [[C],[A],[B]], [[C],[B],[A]] ] 一般而言: [1,2,…,n

我正在寻找一个这样的算法

permutateBuckets([A,B,C])
并给出以下结果:

[ [[A,B,C]],
  [[A,B],[C]], [[A,C],[B]], [[B,C],[A]], [[A],[B,C]], [[B],[A,C]], [[C],[A,B]],
  [[A],[B],[C]], [[A],[C],[B]], [[B],[A],[C]], [[B],[C],[A]], [[C],[A],[B]], [[C],[B],[A]]
]
一般而言:

[1,2,…,n]的排列应包括1到n个包含输入值的存储桶的任何可能排列,存储桶中的值顺序不相关(例如[1,2]等于[2,1]),只有包含存储桶的顺序才重要(例如[1,2],[3]]不同于[3],[1,2]])


每个输入元素必须正好位于一个存储桶中,才能使结果有效(例如,[1,2]的输入不能给出[[1]](缺少2)或[[1,2],[1]](1出现两次)作为输出)。

最简单的方法是递归:

 Make [[A]] list
 Insert new item in all possible places - 
    before current sublists
    between all sublists
    after current sublists
    into every sublist
例如,列表
[[B][A]]
生成5个带有项目C的新列表-插入C的位置为:

  [   [B]   [A]   ]
    ^  ^  ^  ^  ^
三个二级列表产生5+5+3=13个三级列表

替代方式:
生成从1…1到1…n的所有n长度非减量序列,并为每个序列生成唯一的置换。 这些排列上的值对应于每个项目的桶号。例如,122序列给出了3个对应于分布的排列:

1 2 2     [1],[2, 3] 
2 1 2     [2],[1, 3] 
2 2 1     [3],[1, 2]
在任何情况下,分布的数量都会迅速增加(有序钟形编号
1、3、13、75541、468347293、5458357087261102247563…

在Delphi中实现迭代方法(完整的FP兼容代码at)

现在是Python递归实现()


编辑:@mhmnn在使用自定义项进行输出时克隆了此代码。

递归方法当然更容易,但可能不是最有效的解决方案。您对这种递归方法满意吗?(我没有解决方案,只是想知道您的期望)。我还认为递归方法将是最有效的方法-我对递归或顺序都很好。我将尝试明天编写该方法的代码并发布我的结果,谢谢!我基于您的Python代码在JavaScript中实现了它,并通过接受一个带有被置换值的数组来扩展它。代码可以在这里找到:请随意将代码添加到您的答案中,以获得更高的可见性-请注意,Lodash.js用于cloneDeep函数。
 procedure GenDistributions(N: Integer);
  var
    seq, t, i, mx: Integer;
    Data: array of Byte;
    Dist: TBytes2D;
  begin
    SetLength(Data, N);

    //there are n-1 places for incrementing
    //so 2^(n-1) possible sequences
    for seq := 0 to 1 shl (N - 1) - 1 do begin
      t := seq;
      mx := 0;
      Data[0] := mx;
      for i := 1 to N - 1 do begin
        mx := mx + (t and 1); //check for the lowest bit
        Data[i] := mx;
        t := t shr 1;
      end;

      //here Data contains nondecreasing sequence 0..mx, increment is 0 or 1
      //Data[i] corresponds to the number of sublist which item i belongs to

      repeat
        Dist := nil;
        SetLength(Dist, mx + 1); // reset result array into [][][] state

        for i := 0 to N - 1 do
          Dist[Data[i]] := Dist[Data[i]] + [i]; //add item to calculated sublist

        PrintOut(Dist);
      until not NextPerm(Data);  //generates next permutation if possible

    end;
import copy
cnt = 0

def ModifySublist(Ls, idx, value):
    res = copy.deepcopy(Ls)
    res[idx].append(value)
    return res

def InsertSublist(Ls, idx, value):
    res = copy.deepcopy(Ls)
    res.insert(idx, [value])
    return res

def GenDists(AList, Level, Limit):
    global cnt
    if (Level==Limit):
        print( AList)
        cnt += 1
    else:
        for i in range(len(AList)):
            GenDists(ModifySublist(AList, i, Level), Level + 1, Limit)
            GenDists(InsertSublist(AList, i, Level), Level + 1, Limit)
        GenDists(InsertSublist(AList, len(AList), Level), Level + 1, Limit)

GenDists([], 0, 3)
print(cnt)