我有一个n x m的数组(可以是任何大小的数组,但不会是1 x m),并且无论数组大小如何,我都希望分别旋转/移动每个正方形环。
无论数组的大小如何,我如何交替旋转/移位每个平方环。
请注意:我不是要计算数组中的值,而是要移动值。
我的思想过程是获取每个“平方环”的值,并将它们放入一行,然后做一个circshift,然后将它们放回到另一个数组中。
我遇到了尝试将值恢复为原始n x m数组大小的问题,我不确定如何遍历不同n x m数组的过程。
粉红色突出显示的部分,箭头的左侧是数组的起始位置,它是“循环”,绿色突出显示的部分,箭头的右侧是我尝试创建的值的旋转/移位类型。 该数组可能有3个以上的“循环”,这只是一个例子。
以下代码:
I=[1:5;6:10;11:15;16:20;21:25;26:30]
[rw,col] = size(I);
outer_1=[I(1,:),I(2:end-1,end).',I(end,end:-1:1),I(end-1:-1:2,1).'] %get values in one row (so I can shift values)
outer_1_shift=circshift(outer_1,[0 1]) %shift values
new_array=zeros(rw,col);
Ps:我正在使用Octave 4.2.2 Ubuntu 18.04
答案 0 :(得分:1)
因此,我的想法与Andy's comment中的想法相同。不过,由于我已经在准备一些代码,所以这是我的建议:
% 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
我是对的,“移动方向”会随着每个循环而变化吗?
希望有帮助!
警告:我尚未测试通用性。因此,请报告您可能遇到的任何错误。
答案 1 :(得分:1)
编辑:Circshift功能已针对Octave 5.0进行了更改,上一次编辑使其与以前的版本兼容
1;
function r = rndtrip (n, m, v)
rv = @(x) x - 2 * (v - 1);
r = [v * ones(1,rv(m)-1) v:n-v+1 (n-v+1)*ones(1,rv(m)-2)];
if (rv(m) > 1)
r = [r n-v+1:-1:v+1];
endif
endfunction
function idx = ring (n, m , v)
if (2*(v-1) > min (n, m))
r = [];
else
r = rndtrip (n, m, v);
c = circshift (rndtrip (m, n, v)(:), - n + 2 * v - 1).';
idx = sub2ind ([n m], r, c);
endif
endfunction
# your I
I = reshape (1:30, 5, 6).';
# positive is clockwise, negative ccw
r = [1 -1 1];
for k = 1:numel(r)
idx = ring (rows(I), columns(I), k);
I(idx) = I(circshift(idx(:), r(k)));
endfor
I
给予
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