具有可变长度和备用列表内容的列表排列

时间:2018-10-19 06:15:38

标签: c# algorithm list combinations permutation

我正在尝试列出变量的所有排列,其中每个变量具有2个不能在相同排列中的替代项。

比方说,我们有2个变量A和B,但我需要将它们与索引一起使用,例如A1,A2和B1,B2。更复杂的是,“ 1”索引可以单独出现,不允许与另一个“ 1”一起使用,“ 2”索引不能单独出现。 所以我需要的是:


  • A1
  • B1
  • A1 B2
  • B1 A2

使用3个变量A1,A2,B1,B2,C1,C2:

  • A1
  • A1 B2
  • A1 C2
  • A1 B2 C2
  • B1
  • B1 A2
  • B1 C2
  • B1 A2 C2
  • C1
  • C1 A2
  • C1 B2
  • C1 A2 B2

我需要n个变量(n1,n2)。 我找到了这个,但是它并没有真正帮助我:permutations variable length,但是不太合适。 实际上,我目前根本不知道如何处理此问题。

1 个答案:

答案 0 :(得分:0)

我不确定我是否正确解决了您的问题,但请尝试一下。对于此特定的集创建,我采用了将问题分解为第一个条目(如A1和第二个条目(如A2)的方法。我创建了以下算法:

  1. 根据输入n创建所有第一个条目的列表(对于n == 3则为{A1, B1, C1}
  2. 根据输入n创建所有第二个条目的列表(对于n == 3{A2, B2, C2}

  3. 对于每个第一个条目,例如A1

    1. 对于第二个条目的powerset中的每个集合
    2. 如果没有像A1A2这样的冲突
      1. 连接例如{B2, C2}创建类似于B2C2的串联
      2. 将新商品= firstEntry + concatenated set添加到我的自定义商品列表中
  4. 返回自定义集

对于该实现,我在算法步骤3.1中使用了this。导致以下实现:

    private List<string> GetCustomPermutations(int count)
    {
        if(count < 1)
        {
            return new List<string>();
        }

        List<string> firstEntries = new List<string>();
        List<string> secondEntries = new List<string>();

        // Create list of firstEntries = {A1, B1, ...} and secondEntries = {A2, B2, ...} from count
        for (int i = 0; i < count; i++)
        {
            firstEntries.Add((char)('A' + i) + "1");
            secondEntries.Add((char)('A' + i) + "2");
        }

        // Get Powerset of second Entries
        string[][] FullPowerSet = FastPowerSet(secondEntries.ToArray());

        List<string> CustomSet = new List<string>();
        foreach (string firstEntry in firstEntries)
        {
            for (int i = 0; i < FullPowerSet.Length; i++)
            {
                // join the second array dimension to create the appended entry
                string appendedEntry = string.Join("", FullPowerSet[i]);

                // Avoid adding the firstentry char to the appended aswell
                if (appendedEntry.Contains(firstEntry[0]))
                {
                    continue;
                }
                CustomSet.Add(firstEntry + appendedEntry);
            }
        }
        return CustomSet;
    }

    // Create a powerset of every input array, see https://stackoverflow.com/questions/19890781/creating-a-power-set-of-a-sequence
    public static T[][] FastPowerSet<T>(T[] seq)
    {
        var powerSet = new T[1 << seq.Length][];
        powerSet[0] = new T[0]; // starting only with empty set
        for (int i = 0; i < seq.Length; i++)
        {
            var cur = seq[i];
            int count = 1 << i; // doubling list each time
            for (int j = 0; j < count; j++)
            {
                var source = powerSet[j];
                var destination = powerSet[count + j] = new T[source.Length + 1];
                for (int q = 0; q < source.Length; q++)
                    destination[q] = source[q];
                destination[source.Length] = cur;
            }
        }
        return powerSet;
    }