大型集合的独特排列

Cad*_*ade 4 ruby algorithm

我正试图找到一种方法来为y长度的x值生成唯一的排列.我想要做的是:

[0,1].unique_permutations(15)
# => [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
#     [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1],
#     ... massive snip
#     [1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1],
#     [1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1],
#     ... massive snip
#     [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
#     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
Run Code Online (Sandbox Code Playgroud)

要清楚,我知道这是可能的:

[0, 0, 0, 1, 1, 1].permutation.count
# => 720
[0, 0, 0, 1, 1, 1].permutation.to_a.uniq.count
# => 20
Run Code Online (Sandbox Code Playgroud)

但这与我正在寻找的并不完全相同,对于长列表而言,性能变得不切实际:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].permutation.count
# => 479001600 (after a long wait...)
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1].permutation.to_a.uniq.count
# => 1 (didn't actually run this - answer is obvious)
Run Code Online (Sandbox Code Playgroud)

我能找到的最近的东西是python的这个答案,但遗憾的是我不知道python并且无法弄清楚如何将它移植到Ruby.

我确定这类问题还有其他算法,但我真的很想把它保存在Ruby中.

phs*_*phs 8

您正在寻找的是n一组自身的笛卡尔积(在您的示例中具有n = 15过度设置[0, 1].)这与#permutation您在问题后面引用的列表不同.

此列表的大小随指数级增长n.对于所有人而言n,实际上实现它是不切实际的.你可以改用发电机(原谅我生锈的红宝石):

class Array
  def cartesian_power(n)
    current = [0] * n
    last = [size - 1] * n

    loop do
      yield current.reverse.collect { |i| self[i] }
      break if current == last

      (0...n).each do |index|
        current[index] += 1
        current[index] %= size

        break if current[index] > 0
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

然后:

>> [0, 1].cartesian_power(3) { |l| puts l.inspect }
[0, 0, 0]
[0, 0, 1]
[0, 1, 0]
[0, 1, 1]
[1, 0, 0]
[1, 0, 1]
[1, 1, 0]
[1, 1, 1]
=> nil

>> %w{a b c}.cartesian_power(2) { |l| puts l.inspect }
["a", "a"]
["a", "b"]
["a", "c"]
["b", "a"]
["b", "b"]
["b", "c"]
["c", "a"]
["c", "b"]
["c", "c"]
=> nil
Run Code Online (Sandbox Code Playgroud)