我正试图找到一种方法来为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],
要明确,我知道这是可能的:
[0, 0, 0, 1, 1, 1].permutation.count
# => 720
[0, 0, 0, 1, 1, 1].permutation.to_a.uniq.count
# => 20
但这与我正在寻找的并不完全相同,而长期列表的表现变得不切实际:
[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)
我能找到的最近的东西是this answer for python,但遗憾的是我不知道python并且无法弄清楚如何将它移植到Ruby。
我确信这类问题还有其他算法,但我真的很想把它保存在Ruby中。
答案 0 :(得分: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
然后:
>> [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
答案 1 :(得分:2)
这是一个想法 - 对于[0,1]
集合,您可以从二进制中的0开始计算,并且只需插入前导零,直到您有一个长度为15的字符串。
n = 15
max = ('1' * n).to_i(2)
(0..max).map do |i|
i.to_s(2).rjust(n).gsub(" ","0")
end
这个结果几乎可以立即返回置换字符串;将它们转换为整数数组(将.split('').map(&:to_i)
添加到块中)需要一两秒钟。
这不是一个包罗万象的解决方案(它假设源数组的每个元素至少出现n
次),但它适用于您的示例。它也应该可以翻译成其他数字基础(我认为你可以在Ruby中达到36)。
编辑:以及其他数字基数因其大小而无法正常运作。但是他们应该让你知道你正在寻找多少独特的排列;例如3个元素的长度15 = 14,348,906,4个元素是1,073,741,823(也许更熟悉数学的人可以证实这一点)。
答案 2 :(得分:2)
递归解决方案看起来像这样(伪代码,因为我的Ruby不是很好):
unique_permutations(n,values) {
if (n == 0) {
return EmptyList
} else {
lst = unique_permutations(n-1,values)
newList = EmptyList
for i in values {
for j in lst {
newList.append(prependElementToList(i,j))
}
}
return newList
}
}
然后可以使用unique_permutations(15,[0,1])
答案 3 :(得分:-1)
对于仍然磕磕绊绊的人。由于ruby 1.9.2,Array#repeated_permutations也是如此。
1.9.2-p320 :056 >
puts %w(a b c).repeated_permutation(2).map(&:inspect)
["a", "a"]
["a", "b"]
["a", "c"]
["b", "a"]
["b", "b"]
["b", "c"]
["c", "a"]
["c", "b"]
["c", "c"]
=> nil
1.9.2-p320 :057 >