迭代所有整数向量,总结到MATLAB中的某个值?

时间:2013-12-05 14:50:14

标签: matlab vector

我想找到一个干净的方法,以便我可以迭代所有长度正整数的向量,比如n(称为x),这样在MATLAB中sum(x) == 100

我知道这是一项指数级复杂的任务。如果长度足够小,比方说2-3我可以通过for循环(我知道这是非常低效的)来实现它,但是更长的向量怎么样?

提前致谢,

2 个答案:

答案 0 :(得分:2)

这是一个使用递归的快速而脏的方法。我们的想法是,要生成长度为k且总和为n的所有向量,您首先生成长度为k-1的向量,每个向量n-ii=1..n ,然后在每个结尾添加一个额外的i

您可以通过在每个循环中预先分配x来加快速度。

请注意,输出的大小为( n + k - 1选择 n )行和 k 列。

function x = genperms(n, k)

if k == 1
    x = n;
elseif n == 0
    x = zeros(1,k);
else
    x = zeros(0, k);
    for i = 0:n
        y = genperms(n-i,k-1);
        y(:,end+1) = i;
        x = [x; y];
    end
end

修改

正如评论中所提到的,这会遇到大型nk的内存问题。流传输解决方案是优选的,其一次一个地生成输出。在像Haskell这样的非严格语言中,这非常简单 -

genperms n k
    | k == 1    = return [n]
    | n == 0    = return (replicate k 0)
    | otherwise = [i:y | i <- [0..n], y <- genperms (n-i) (k-1)]

>> mapM_ print $ take 10 $ genperms 100 30
[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,100]
[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,99]
[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,2,98]
[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,3,97]
[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,4,96]
[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,5,95]
[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,6,94]
[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,7,93]
[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,8,92]
[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,9,91]

几乎瞬间运行 - 无需担心内存问题。

在Python中,使用生成器和yield关键字可以实现几乎一样简单的事情。在Matlab中它肯定是可能的,但我将翻译留给你了!

答案 1 :(得分:1)

这是一次生成所有向量的一种可能方法(会给中等大n带来内存问题):

s = 10; %// desired sum
n = 3; %// number of digits
vectors = cell(1,n);
[vectors{:}] = ndgrid(0:s); %// I assume by "integer" you mean non-negative int
vectors = cell2mat(cellfun(@(c) reshape(c,1,[]), vectors, 'uni', 0).');
vectors = vectors(:,sum(vectors)==s); %// each column is a vector

现在你可以迭代这些向量:

for vector = vectors %// take one column at each iteration
    %// do stuff with the vector
end

为了避免内存问题,最好根据需要生成每个向量,而不是最初生成所有向量。以下方法迭代一个n循环中的所有可能for - 向量(无论n),拒绝那些和不是所需值的向量:

s = 10; %// desired sum
n = 3;; %// number of digits
for number = 0: s^n-1
    vector = dec2base(number,s).'-'0'; %// column vector of n rows
    if sum(vector) ~= s
        continue %// reject that vector
    end
    %// do stuff with the vector
end