Ruby:计算唯一排列的数量,而不使用数据集中带有重复项的.permutation

时间:2016-05-25 09:17:48

标签: ruby algorithm permutation

我需要一种方法来接收不同长度和内容的字符串,返回排列的数量而不重复。我写了以下内容来试图解决这个问题

def permutations(n)
  k = n.to_s.chars.uniq.length
  e = n.to_s.length
  m = (1..e).reduce(1, :*)
  p = (1..k).reduce(1, :*)
  l = m / p
  case
    when k == 1 then 1
    when k < e then l
    else m 
  end
end 

以上是返回一些我已经困惑了几天的结果,我已经意识到,uniq需要检查的重复值超过1组。

如果我通过bbbb789,我会210这是正确的。但是,如果我有一个包含两个重复项的集合,例如73839,则预期结果为60 but I reach 5

我昨天意识到问题所在,但我无法找到重复数据的方法

我的第一个解决方法是使用

k = n.to_s.chars.uniq.length
m = n.to_s.chars.length 
return 1 if k <= 1 
n.to_s.chars.permutation(m)to_a.uniq.size

这也有效,但需要一个年龄来循环更长的集合的所有排列

1 个答案:

答案 0 :(得分:2)

TL; DR:

def factorial(n)
  (1..n).inject(1, :*)
end

str = '73839'

# https://stackoverflow.com/questions/5470725/how-to-group-by-count-in-array-without-using-loop
chars_count = str.split('').inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }

# https://stackoverflow.com/questions/9560335/ruby-hash-to-array-of-values
chars_fact = chars_count.values.inject(1) {|result, element| result*factorial(element)}

p "There are #{factorial(str.length)/chars_fact} permutations without duplicates."

解释不是很好:

嗯,这主要是一个数学问题:

注意:当我写n!你应该阅读&#34; factorial n&#34;它代表整数1 * 2 * ... * n。您可以在此处找到ruby实现:https://stackoverflow.com/a/12415362/4480140

如果你有n和&m 39,那么找到没有重复的排列数的公式是n选择m + n,即(m + n)!/(n!* m !)。

然后,如果我们有'aazzerty&#39;我们是说我们有一个和一个人。所以我们有'aabbbbbb&#39;,我们有2种选择8种置换方式。其中一种可能的排列是&#39; bbabbbab&#39;然后我们对b进行了改变。我们知道这些b包含2个z和1个(e,r,t,y)。我们将置换所有不是z或a的东西。我们有2种选择6种方法。我们重复这个过程......

最后,排列数为(2选8)(2选6)(1选4) ... (1选2)。我们可以取消,实际上我们得到8!/(2!* 2!* 1!* 1!* 1!* 1!)。

基本上,我们必须计算每个角色的数量,取所有这些数字的阶乘,将它们相乘。这是分母,分子是字符串长度的阶乘。