生成所有组合以扩展到大列

generate all combinations to extend to large columns

我有 C 列,我想在其中填充 N 元素的所有组合 (C>N)。我如何在 Matlab 中完成?
例子:C=5,N=3;然后将 N 从 1 到 N 即 1 到 3 的所有组合填充到 C=5 列中。我试过 NchooseK 但无法实现。预期输出如下所示:

输出:11111, 11112, 11122, 11222, ....., 22222, 22223, 22233, ....., 33333, ..... 12312, 12313, 12323, ...等等...
以这种方式,1 到 N 的所有组合最多填充 C 列。我的C大到40,N大到10
Matlab有什么办法吗

这是一个树遍历问题。这是一个 DFS 方法:

function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,''); % wrap the iterative function
end

function s = prtstr(C,N,prefix)
s = cell(N^C,1);
if C == 1
    for ii = 1:N
        s{ii} = [prefix, num2str(ii)];
    end
else
    BlockLen = N^(C-1);
    for ii = 1:N
        s((1+(ii-1)*BlockLen) : (ii*BlockLen)) = ....
            prtstr(C-1,N,[prefix, num2str(ii)]);
    end
end
end

输出是一个包含所有组合字符串的元胞向量。

>> s = GetCombinations(5,3)

s = 

    '11111'
    '11112'
    '11113'
    '11121'
    '11122'
    '11123'
    '11131'
    '11132'
    '11133'
    '11211'
    '11212'
    '11213'
    '11221'
    '11222'
    '11223'
    '11231'
    '11232'
    ....

编辑:跳过重复案例。例如,1111211121 被认为是相同的,只列出第一个。

function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,'',1);
s = s(~cellfun(@isempty,s));
end

function s = prtstr(C,N,prefix,startN)
s = cell(N^C,1);
if C == 1
    for ii = startN:N
        s{ii} = [prefix, num2str(ii)];
    end
else
    BlockLen = N^(C-1);
    for ii = startN:N
        s((1+(ii-1)*BlockLen) : (ii*BlockLen)) = ....
            prtstr(C-1,N,[prefix, num2str(ii)], ii);
    end
end
end

>> s = GetCombinations(5, 3)

s = 

    '11111'
    '11112'
    '11113'
    '11122'
    '11123'
    '11133'
    '11222'
    '11223'
    '11233'
    '11333'
    '12222'
    '12223'
    '12233'
    '12333'
    '13333'
    '22222'
    '22223'
    '22233'
    '22333'
    '23333'
    '33333'

编辑:对于大 CN,预分配元胞数组是不可行的。事实上,大多数细胞都是空的。哪些是空的可以预先确定,但这本身就是一个有趣的问题。然而,我只是随时附加元胞数组,而不是预先分配它。所以有点慢,但它有效。

function s = GetCombinations(C,N)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
s = prtstr(C,N,'',1);
s = s(~cellfun(@isempty,s));
end

function s = prtstr(C,N,prefix,startN)
s = cell(0,1);
if C == 1
    nt = N-startN+1;
    t = cell(nt,1);
    for ii = 1:nt
        t{ii} = [prefix, num2str(ii+startN-1)];
    end
    s = t;
else
    for ii = startN:N
         t = prtstr(C-1,N,[prefix, num2str(ii)], ii);
         s = [s;t];
    end
end
end

编辑:无记忆版本。 请求 (C,N) = (20,10),结果太大,无法保存在内存中。一种可能的解决方案是只打印结果而不存储它。下面是代码,经过测试。

function GetCombinations(C,N, fh)
C = int64(C);
N = int64(N);
assert(C>0 && N>0, 'Invalid input')
prtstr(C,N,'',1, fh);
end

function prtstr(C,N,prefix,startN, fh)
if isempty(fh) % assign fh = [] if you do not want text file output
    fh = 1; % print to command window
end
if C == 1
    for ii = 1:N-startN+1
        fprintf(fh, '%s%d\n', prefix, ii+startN-1);
    end
else
    for ii = startN:N
        prtstr(C-1,N,[prefix, num2str(ii)], ii, fh)
    end
end
end

该函数接受一个额外的输入参数 fh,它是一个文件句柄。因为 (20,10) 有相当多的输出行(10m+ 行和 200MB+),您可能希望将结果直接打印到文本文件中。为此,

fh = fopen('testout.txt','w');
GetCombinations(20,10,fh)
fclose(fh)

否则,如果你真的想把结果打印到命令window,使用

GetCombinations(20,10,[])