总数与n位数

时间:2015-01-27 23:13:15

标签: ruby function loops math nested

所以我为你得到了一些绊脚石。我需要编写一个函数,它接受一个数字(称为K)并输出n个数字,其中总和如果这些数字== K.

例如,如果我给出这个函数(100,3),它将输出[1,2,97],[1,3,96],[1,4,95] ... [97,1, 2]

我的功能是三位数:

k = 100
r = []
0.upto(k/2) do |a|
    (a+1).upto(k/2) do |b|
        c = k-(a+b)
        r << [a,b,c]
    end
end

我如何编写这个需要n位数的函数?

1 个答案:

答案 0 :(得分:0)

这可能不是世界上最好的解决方案(需要的内存随O(k^3)而增长),但它是一个解决方案。我欢迎提出改进建议。

您可能有兴趣阅读integer partitions,这是我们在此重复计算的内容。

您正在寻找一个功能f(k,n),它会计算将数字k划分为n部分的方式的数量。问题的部分原因是,在计算分区两次时很难分辨。

我将通过使用另一个函数g(k,n,s)来解决此问题,该函数计算将数字k划分为n部分的方式的数量,其中允许的最大值是 s。例如,我们不计算(90,8,2)中的分区(64,20,16)g(100,3,60),因为它们使用的值大于s=60

g(k,n,s) = f(k,n)时{p> s>=k(即我们不会在分区中允许的值上放置最大值)。


关于g(k,n,s)的一些事实:

  • k==n隐含g=1,因为将k分区为k部分的唯一方法是使用所有1 s(因此s是因为我们使用尽可能少的数字而无关紧要)
  • n>k隐含g=0,因为我们无法将k分区为k部分以上
  • s==1隐含g=1如果k==ng=0,则因为放置1的最大值只允许k的分区k部分(全部)
  • n==1隐含g=1如果s>=kg=0,则kn=1部分的唯一分区要求我们使用k {1}}本身在分区
  • s<RoundUp(k/n)隐含g=0,因为我们无法使用小于k的值将n分割为k/n部分;例如,我们不能仅使用小于100的值对425个分区进行分区。
  • s>k-n+1隐含g(k,n,s) = g(k,n,s-1),因为在s添加任何新分区后增加最大值k-n+1;例如,1003部分的任何分区都不会包含大于100-3+1 = 98的数字
  • 在所有其他情况下,
  • g(k,n,s) = g(k,n,s-1) + g(k-s,n-1,s)。这只会使用值s将所有分区添加到我们使用最大值s-1
  • 计算的所有先前分区中

现在我只选择最大数量K并将所有这些事实抛出到嵌套的for循环中,并推导出g(k,n,s)的每个值。要获得f(k,n),我只需找到g(k,n,k)


这是算法,不适合大K

g = (K by K by K) array of all zeros

for k = 1:K
    for n = 1:K
        for s = 1:K

            if (k==n)
                val = 1;
            else if (n>k)
                val = 0;
            else if s==1
                val = int(k==n);
            else if n==1
                val = int(s>=k);
            else if s<RoundUp(k/n)
                val = 0;
            else if s>(k-n+1)
                val = g(k,n,s-1);
            else
                val = g(k,n,s-1) + g(k-s,n-1,s);
            end

            g(k,n,s) = val;

        end
    end
end

对于f(100,3) = g(100,3,100),我获得了833个唯一分区,如果您使用强力方法,则可以看到这些分区是正确的。如果你看到任何错误,请指出错误。