Как говорится в комментариях к ОП, StackOverflow не является услугой кода письма. Сказав это, это была интересная проблема, и я решил сделать исключение и ответить на него в любом случае.
Формальности в сторону ...
Я думаю, что у меня есть общее решение, которое также может обрабатывать несколько (все?) Крайние случаи, как G
с нулевыми строками и т.д. Приведенный ниже код генерирует один экземпляр x
матрица.
Создание n
m
массива матрицы с размерностью этих x
с оставляются «в качестве упражнения для читателя» (в основном потому, что это не определенно, хочет ли OP как массив ячеек матриц или 4-D логического/двойной массив).
Чтобы понять, что он делает, см. Комментарии в кодах + имена переменных. Я надеюсь, что это достаточно ясно (и что я не пропустил никаких случаев с краями).
function x = q37055681(G)
%% Input
if nargin < 1
G = [ 1 1 0 0 1
0 1 1 1 0
1 0 1 1 1 ];
end
%% Input analysis:
[A_ROWS,OUT_COLS] = size(G);
transitions = find(diff(padarray(G.',1,false,'both').',1,2).');
tr_per_ln = hist(ceil(transitions/(size(G,2)+1)),size(G,1))/2;
A_COLS = max(tr_per_ln);
missing_trans_per_line = A_COLS - tr_per_ln;
groups_of_ones = diff(reshape(transitions,2,[]),1,1); % < result of RLE which ignores 0's
% Count "fixing" based on the external definition of what to do with only 1 group per
% line (in this case, count it in the first element of A):
insrt = @(what, into, where) cat(2, into(1:where-1), what, into(where:end));
for indZ = 1:sum(missing_trans_per_line(:))
next_incomplete = find(missing_trans_per_line,1);
groups_of_ones = insrt(0, groups_of_ones, A_COLS*next_incomplete-...
(missing_trans_per_line(next_incomplete)-1));
missing_trans_per_line(next_incomplete) = missing_trans_per_line(next_incomplete)-1;
end
A = reshape(groups_of_ones,A_COLS,[]).';
%% Generation of output:
x = zeros(size(G));
for indR = 1:A_ROWS
tokens = cell(sum(A(indR,:)~=0),1);
switch numel(tokens)
case 0
% we don't need to do anything, the entire line is 0.
continue;
case 1
tokens{1} = repelem(true,A(indR,1));
otherwise
for indT = 1:numel(tokens)-1
tokens{indT} = [repelem(true,A(indR,indT)) 0];
end
tokens{end} = repelem(true,A(indR,find(A(indR,:),1,'last')));
end
zero_tokens = repmat({0},[OUT_COLS-sum(A(indR,:))-(numel(tokens)-1),1]);
% Now we need to build a vector that selects randomly but SEQUENTIALLY from
% EITHER tokens or zero_tokens.
cell_to_pick_from = [ones(1,numel(tokens)) zeros(1,numel(zero_tokens))];
choosing_order = cell_to_pick_from(randperm(numel(cell_to_pick_from)));
%^Here's where the randomness comes in:
x_line = [];
for indC = 1:numel(choosing_order)
if choosing_order(indC)
% if it's 1, choose from "tokens"
token = tokens{sum(choosing_order(1:indC)==1)};
else
% if it's 0, choose from "zeros"
token = zero_tokens{sum(choosing_order(1:indC)==0)};
end
x_line = [x_line token]; %#ok
end
x(indR,:) = x_line;
end
end
Почему у этого есть тег R? – lmo
Какие входные данные? Какая желаемая производительность? что ты уже испробовал? – Crowley
@lmo Возможно, по той же причине у него есть тег 'matlab' - R, Matlab и Octave, которые обычно используются для обработки матриц. – Crowley