Итак, у меня была та же идея, что и в комментарии Энди . Тем не менее, так как я уже готовил некоторый код, вот мое предложение:
% Input.
I = reshape(1:30, 5, 6).'
[m, n] = size(I);
% Determine number of loops.
nLoops = min(ceil([m, n] / 2));
% Iterate loops.
for iLoop = 1:nLoops
% Determine number of repetitions per row / column.
row = n - 2 * (iLoop - 1);
col = m - 2 * (iLoop - 1);
% Initialize indices.
idx = [];
% Add top row indices.
idx = [idx, [repelem(iLoop, row).']; iLoop:(n-(iLoop-1))];
% Add right column indices.
idx = [idx, [[iLoop+1:(m-(iLoop-1))]; repelem(n-(iLoop-1), col-1).']];
if (iLoop != m-(iLoop-1))
% Add bottom row indices.
idx = [idx, [repelem(m-(iLoop-1), row-1).'; (n-(iLoop-1)-1:-1:iLoop)]]
end
if (iLoop != n-(iLoop-1))
% Add left column indices.
idx = [idx, [[(m-(iLoop-1))-1:-1:iLoop+1]; repelem(iLoop, col-2).']]
end
% Convert subscript indices to linear indices.
idx = sub2ind(size(I), idx(1, :), idx(2, :));
% Determine direction for circular shift operation.
if (mod(iLoop, 2) == 1)
direction = [0 1];
else
direction = [0 -1];
end
% Replace values in I.
I(idx) = circshift(I(idx), direction);
end
% Output.
I
К сожалению, я не мог придумать более разумного способа генерирования индексов, поскольку вам нужно поддерживать правильный порядок и избегать двойных индексов. Как видите, я получаю индексы индекса по отношению к I
, поскольку это можно сделать довольно просто, используя размеры матрицы и количество циклов. Тем не менее, для операции circshift
и последующей замены значений в I
линейные индексы более удобны, поэтому операция sub2ind
.
Вход и выход выглядят так:
I =
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30
I =
6 1 2 3 4
11 8 9 14 5
16 7 18 19 10
21 12 13 24 15
26 17 22 23 20
27 28 29 30 25
Я был прав, что «направление сдвига» меняется с каждым циклом?
Надеюсь, это поможет!
Внимание: я еще не проверял общность. Поэтому, пожалуйста, сообщайте о любых ошибках, с которыми вы можете столкнуться.