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

时间:2017-02-28 14:39:27

标签: matlab combinations element

我有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有没有办法。

1 个答案:

答案 0 :(得分:1)

这是一个树遍历问题。这是一个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)

否则,如果您确实要将结果打印到命令窗口,请使用

GetCombinations(20,10,[])