数组的交替和移位部分

时间:2019-06-13 05:06:21

标签: arrays octave

我有一个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);

Shift Process

Ps:我正在使用Octave 4.2.2 Ubuntu 18.04

2 个答案:

答案 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

run it on tio