有限的重复排列

时间:2015-06-16 16:24:38

标签: arrays ruby permutation

我正在尝试生成15个数组中某些值的所有可能组合,最多可添加50个。

$a = [3, 4, 1, 2, 5]
print $a.repeated_permutation(15).to_a

在这种情况下,

[2,2,2,2,4,4,4,4,4,4,4,4,4,3,3]
[2,2,2,4,2,4,4,4,4,4,4,4,4,3,3]
[2,2,4,2,2,4,4,4,4,4,4,4,4,3,3]

都是可能的答案。

经过一番调查后,我意识到执行此操作的代码有点过头,但如果有可能对其他人有所帮助,我会提出问题。

关于我正在做什么的参考,项目欧拉,问题114.这是非常困难的,所以我试图只解决一个案例,我的50空间长网格只填充3单元长块。这些块必须至少由一个空格分隔,所以我将这些块计为4.这个(有一些调整,我已经遗漏了,因为这已经足够令人困惑)允许12个块加上3个单个空白,或者最大值十五个元素。

1 个答案:

答案 0 :(得分:1)

<强>方法

我认为递归是这里的方法,你的递归方法如下所示:

def recurse(n,t)

,其中

  • n是所需元素的数量;和
  • t是必需的总数。

如果我们让@arr成为您给出的整数数组,recurse(n,t)将返回一个数组,其中包含来自n的{​​{1}}个元素的所有排列,其总和为{{1} }}

<强>假设

我假设@arr的元素是非负整数,按大小排序,但如果它包含负整数,则可以很容易地修改该方法(尽管性能会受到影响)。在不失一般性的情况下,我们可以假设t的元素是唯一的,按增加的幅度排序。

<强>代码

@arr

<强>实施例

@arr

<强>改进

然而,我们可以通过首先计算所有组合,然后计算每种组合的排列来做得更好。

def recurse(n,t)
  if n == 1
    @arr.include?(t) ? [[t]] : nil
  else
    @arr.each_with_object([]) do |i,a|
      break if i > t # as elements of @arr are non-decreasing
      if (ret = recurse(n-1,t-i))
        ret.each { |b| a << [i,*b] }
      end
    end
  end
end

然后我们可以从组合中计算排列:

@arr = [3, 4, 1, 2, 5].sort
  #=> [1, 2, 3, 4, 5]

recurse(1,4)
  #=> [[4]]
recurse(2,6)
  #=> [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]] 
recurse(3,10)
  #=> [[1, 4, 5], [1, 5, 4], [2, 3, 5], [2, 4, 4], [2, 5, 3],
  #    [3, 2, 5], [3, 3, 4], [3, 4, 3], [3, 5, 2], [4, 1, 5],
  #    [4, 2, 4], [4, 3, 3], [4, 4, 2], [4, 5, 1], [5, 1, 4],
  #    [5, 2, 3], [5, 3, 2], [5, 4, 1]] 
recurse(3,50)
  #=> [] 

我们可以估算def combo_recurse(n,t,last=0) ndx = @arr.index { |i| i >= last } return nil if ndx.nil? arr_above = @arr[ndx..-1] if n == 1 arr_above.include?(t) ? [[t]] : nil else arr_above.each_with_object([]) do |i,a| break if i > t # as elements of @arr are non-decreasing if (ret = combo_recurse(n-1,t-i,i)) ret.each { |b| a << [i,*b] } end end end end combo_recurse(1,4) #=> [[4]] combo_recurse(2,6) #=> [[1, 5], [2, 4], [3, 3]] combo_recurse(3,10) #=> [[1, 4, 5], [2, 3, 5], [2, 4, 4], [3, 3, 4]] combo_recurse(3,50) #=> [] combo_recurse(15,50).size #=> 132 combo_recurse(15,50).first(5) #=> [[1, 1, 1, 1, 1, 1, 4, 5, 5, 5, 5, 5, 5, 5, 5], # [1, 1, 1, 1, 1, 2, 3, 5, 5, 5, 5, 5, 5, 5, 5], # [1, 1, 1, 1, 1, 2, 4, 4, 5, 5, 5, 5, 5, 5, 5], # [1, 1, 1, 1, 1, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5], # [1, 1, 1, 1, 1, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5]] 的排列数(由于未应用combo_recurse(2,6).flat_map { |a| a.permutation(a.size).to_a }.uniq #=> [[1, 5], [5, 1], [2, 4], [4, 2], [3, 3]] combo_recurse(3,10).flat_map { |a| a.permutation(a.size).to_a }.uniq #=> [[1, 4, 5], [1, 5, 4], [4, 1, 5], [4, 5, 1], [5, 1, 4], # [5, 4, 1], [2, 3, 5], [2, 5, 3], [3, 2, 5], [3, 5, 2], # [5, 2, 3], [5, 3, 2], [2, 4, 4], [4, 2, 4], [4, 4, 2], # [3, 3, 4], [3, 4, 3], [4, 3, 3]] ,因此会有些高):

(15,50)

即,结果大约有1,600位数。你将在这个平台上运行什么?