2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

組み合わせ数と組み合わせを求める

2
Last updated at Posted at 2026-06-19

グループ数:最大5
各グループの要素数:最大20
各グループから1つずつ選択
グループ数は可変(1~5)
値は cell 配列で渡される
下位グループの要素数は上位グループを超えない
(例:G1=20個なら G2~G5は20個以下)

組み合わせ数を求める関数

function nComb = countCombination(groups)

    % 空グループ除外
    groups = groups(~cellfun('isempty',groups));

    if isempty(groups)
        nComb = 0;
        return;
    end

    nComb = prod(cellfun(@numel, groups));

end

全組み合わせを生成する関数

function comb = makeCombination(groups)

    % 空グループ除外
    groups = groups(~cellfun('isempty',groups));

    nGroup = numel(groups);

    if nGroup == 0
        comb = [];
        return;
    end

    % 各グループの添字
    idx = cell(1,nGroup);

    for k = 1:nGroup
        idx{k} = 1:numel(groups{k});
    end

    % 全組み合わせの添字生成
    G = cell(1,nGroup);
    [G{:}] = ndgrid(idx{:});

    nComb = numel(G{1});

    comb = zeros(nComb,nGroup);

    for k = 1:nGroup
        comb(:,k) = groups{k}(G{k}(:));
    end

end

同一グループが複数ある場合

groups = {
    [10 20 30 40]
    [50 60]
    [70 80]
    [90 100]
    [110 120]
};

groupId = {
    'G1'
    'G2'
    'G2'
    'G3'
    'G4'
};

[comb,nComb] = makeCombination(groups,groupId);

function [comb,nComb] = makeCombination(groups,groupId)

    % グループ統合
    uGroup = unique(groupId,'stable');

    mergedGroups = cell(1,numel(uGroup));

    for k = 1:numel(uGroup)

        idx = strcmp(groupId,uGroup{k});

        tmp = [];

        for m = find(idx(:))'
            tmp = [tmp groups{m}];
        end

        mergedGroups{k} = unique(tmp,'stable');

    end

    % 空グループ除外
    mergedGroups = mergedGroups(~cellfun(@isempty,mergedGroups));

    nGroup = numel(mergedGroups);

    nElem = cellfun(@numel,mergedGroups);

    nComb = prod(nElem);

    % 添字生成
    idx = cell(1,nGroup);

    for k = 1:nGroup
        idx{k} = 1:nElem(k);
    end

    [grid{1:nGroup}] = ndgrid(idx{:});

    comb = zeros(nComb,nGroup);

    for k = 1:nGroup
        comb(:,k) = mergedGroups{k}(grid{k}(:));
    end

end

結果を縦横並び替える

    C = num2cell(comb);
    C = C.';

    または1行で
    C = num2cell(comb).';

	app.UITable.Data = num2cell(comb);
	もしくは
	app.UITable.Data = num2cell(comb).';

    cellから値を変えるなら
    cell2mat

■その2

function result = makeCombination(C)
    
    %----- グループ番号取得 -----
    grp = cell2mat(C(:,1));
    
    uGrp = unique(grp,'stable');
    
    %----- グループごとの候補作成 -----
    groupData = cell(numel(uGrp),1);
    
    for g = 1:numel(uGrp)
    
        rows = find(grp==uGrp(g));
    
        if numel(rows)==1
    
            vals = {};
    
            for c = 2:size(C,2)
    
                if isempty(C{rows,c})
                    break
                end
    
                vals{end+1} = C{rows,c};
            end
    
            groupData{g} = vals;
    
        else
    
            % 同一グループ複数行
            maxCol = 0;
    
            for r = rows(:)'
    
                lastCol = find(~cellfun(@isempty,...
                            C(r,2:end)),1,'last');
    
                maxCol = max(maxCol,lastCol);
    
            end
    
            tmp = cell(1,maxCol);
    
            for k = 1:maxCol
    
                x = cell(numel(rows),1);
    
                for r = 1:numel(rows)
                    x{r} = C{rows(r),k+1};
                end
    
                tmp{k} = x;
            end
    
            groupData{g} = tmp;
    
        end
    
    end
    
    %----- 組み合わせ数 -----
    nChoice = cellfun(@numel,groupData);
    
    combCount = prod(nChoice);
    
    fprintf('Combination Count = %d\n',combCount);
    
    %----- ndgrid -----
    idx = cell(1,numel(groupData));
    
    for k = 1:numel(groupData)
        idx{k} = 1:nChoice(k);
    end
    
    [G{1:numel(groupData)}] = ndgrid(idx{:});
    
    %----- 結果作成 -----
    rowCount = 0;
    
    for g = 1:numel(groupData)
    
        if iscell(groupData{g}{1})
            rowCount = rowCount + numel(groupData{g}{1});
        else
            rowCount = rowCount + 1;
        end
    
    end
    
    result = cell(rowCount,combCount);
    
    for col = 1:combCount
    
        rOut = 1;
    
        for g = 1:numel(groupData)
    
            sel = G{g}(col);
    
            value = groupData{g}{sel};
    
            if iscell(value)
    
                for k = 1:numel(value)
                    result{rOut,col} = value{k};
                    rOut = rOut + 1;
                end
    
            else
    
                result{rOut,col} = value;
                rOut = rOut + 1;
    
            end
    
        end
    
    end
    
end

使用例

C = {
    1 10 20 30 40 []
    2 50 60 [] [] []
    2 70 80 [] [] []
    3 90 100 [] [] []
    4 110 120 [] [] []
    5 130 140 [] [] []
};

result = makeCombination(C);

writematrix(cell2mat(result),'result.xlsx');

■その2

function [result, combCount] = makeGroupCombination(inputCell)
% inputCell:
%   1列目   : グループ番号
%   2列目~ : 値
%   空セル以降は値なし
%
% result:
%   行      : 入力行
%   列      : 組み合わせ
%
% 同一グループの複数行は、同じ選択肢番号で連動する。
% 同一グループ内で値数が異なる場合、短い行は先頭から繰り返す。

    %% 入力チェック
    if isempty(inputCell) || size(inputCell,2) < 2
        error('inputCellは、グループ番号列と値列を含めてください。');
    end

    groupNo = cell2mat(inputCell(:,1));

    if any(~isfinite(groupNo)) || any(groupNo ~= fix(groupNo))
        error('1列目のグループ番号は整数にしてください。');
    end

    if any(groupNo < 1) || any(groupNo > 5)
        error('グループ番号は1~5にしてください。');
    end

    uniqueGroup = unique(groupNo,'stable');

    % グループ番号が 1,2,3,... と連続しているか確認
    if ~isequal(uniqueGroup, 1:numel(uniqueGroup))
        error(['グループ番号は連続して指定してください。' newline ...
               '例:グループ1の次にグループ3だけを指定することはできません。']);
    end

    %% 各入力行の値を取り出す
    nInputRow = size(inputCell,1);
    rowValues = cell(nInputRow,1);
    rowValueCount = zeros(nInputRow,1);

    for r = 1:nInputRow

        values = {};

        for c = 2:size(inputCell,2)

            % 空セル以降は値なし
            if isempty(inputCell{r,c})
                break;
            end

            values{end+1} = inputCell{r,c};
        end

        if isempty(values)
            error('入力%d行目に値がありません。', r);
        end

        rowValues{r} = values;
        rowValueCount(r) = numel(values);
    end

    %% 各グループの選択肢数
    nGroup = numel(uniqueGroup);
    groupChoiceCount = zeros(1,nGroup);

    for g = 1:nGroup
        rows = find(groupNo == uniqueGroup(g));

        % 同一グループ内で最大の値数を選択肢数とする
        groupChoiceCount(g) = max(rowValueCount(rows));
    end

    %% 組み合わせ数
    combCount = prod(groupChoiceCount);

    %% 各グループの選択番号を作る
    indexCell = cell(1,nGroup);

    for g = 1:nGroup
        indexCell{g} = 1:groupChoiceCount(g);
    end

    gridCell = cell(1,nGroup);
    [gridCell{:}] = ndgrid(indexCell{:});

    %% 結果作成
    result = cell(nInputRow,combCount);

    for r = 1:nInputRow

        % この入力行が属するグループの位置
        groupIndex = find(uniqueGroup == groupNo(r), 1);

        % そのグループの選択番号
        selectedIndex = gridCell{groupIndex}(:);

        nValue = numel(rowValues{r});

        for col = 1:combCount

            % 値数を超えたら先頭へ戻る
            valueIndex = mod(selectedIndex(col)-1, nValue) + 1;

            result{r,col} = rowValues{r}{valueIndex};
        end
    end
end
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?