Ruby 大集合的唯一置换
我试图找到一种方法,为y长度的x值生成唯一的排列。我希望能够做到的是:Ruby 大集合的唯一置换,ruby,algorithm,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
[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)
我能找到的最接近的东西是,但遗憾的是,我不懂python,也不知道如何将其移植到Ruby
我肯定还有其他算法可以解决这类问题,但我真的很想把它保存在Ruby中。这里有一个想法-对于
[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基)
编辑:好吧,其他基数可能由于其大小而无法正常工作。但是他们应该让你知道你到底在寻找多少独特的排列;e、 g.长度为15=14348906的3个元素,4个元素为1073741823(也许更熟悉数学的人可以证实这一点)。递归解决方案可能是这样的(伪代码,因为我的Ruby不是很好):
然后可以用
unique_置换(15,[0,1])
来调用它。您要查找的是一个集本身的n
-三元笛卡尔积(在您的示例中,n=15
over set[0,1]
),这与您在后面的问题中引用的置换
列表不同
此列表的大小随n
呈指数增长。除了微小的n
之外,实际上实现它是不切实际的。你可以用发电机代替(请原谅我生锈的红宝石):
类数组
def笛卡尔_功率(n)
当前=[0]*n
last=[size-1]*n
环道
产生current.reverse.collect{| i | self[i]}
如果当前==最后一个,则中断
(0…n)。每个do |索引|
当前[索引]+=1
当前[索引]%=大小
如果当前[索引]>0,则中断
结束
结束
结束
结束
然后:
[0,1]笛卡尔幂(3){| l | put 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]
=>零
>>%w{abc}.笛卡尔幂(2){l}放l.inspect}
[“a”,“a”]
[“a”、“b”]
[“a”、“c”]
[“b”、“a”]
[“b”,“b”]
[“b”、“c”]
[“c”、“a”]
[“c”、“b”]
[“c”,“c”]
=>零
适用于仍在这一问题上绊倒的任何人。自从ruby 1.9.2以来,它也做了同样的事情
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 >
{0,1}
的元素只有两种排列:01
和10
。我不确定您在计算什么。@请查看我希望实现的输出的第一个代码块。如果我的预期输出有更准确的术语,我很高兴能更正我的术语。[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0]
是否也在您想要的集合中?是否有任何长度为15的1
和0
列表在其中?@phs是的。15项数组中所有可能显示的0和1。这只是一个简单的基数计算问题。这太棒了。谢谢你的专业术语。现在我可以去读笛卡尔积了。这是一个非常好的,非常聪明的答案。谢谢我希望我能接受两个答案,但是@phs在我的问题中涵盖了更一般的情况(y长度的x值)。
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 >