【问题标题】:generate all combinations to extend to large columns生成所有组合以扩展到大列
【发布时间】:2017-02-28 14:39:27
【问题描述】:

我有 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有什么办法吗?

【问题讨论】:

    标签: matlab combinations element


    【解决方案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,[])
    

    【讨论】:

    • 感谢您的回复。但是有重复的组合,例如“11112”和“11121”具有相同的数字。在这种情况下,我只需要保留一个序列“11112”或“11121”。有什么建议吗?
    • 非常感谢。它适用于小值。但是我的要求正如我在 C 的大值问题中提到的那样,它给出了错误。有什么帮助吗?
    • 对 (C,N) = (20,10) 或 (30,8) 有同样的问题,请问有什么解决方案吗?
    • 错误使用 vertcat 内存不足。键入 HELP MEMORY 作为您的选项。 @Yvon GettCombinations 中的错误>prtstr (line 21) s = [s;t]; GettCombinations 错误>prtstr(第 20 行)t = prtstr(C-1,N,[prefix, num2str(ii)], ii);
    • @Yvon 是否可以让 C=40 和 N=10 没有内存溢出?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2013-06-16
    相关资源
    最近更新 更多