旋转2D矩阵


30

假设我有以下(2D)矩阵:

[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

旋转矩阵逆时针 R倍(未以90个增量,只是通过每次1号),

1  2  3  4             2 3   4  8         3   4   8  12
5  6  7  8    -->      1 7  11 12   -->   2  11  10  16 
9  10 11 12            5 6  10 16         1   7   6  15 
13 14 15 16            9 13 14 15         5   9  13  14

完成的示例:

输入:

2
[[1,  2,  3,  4 ],
 [5,  6,  7,  8 ],
 [9,  10, 11, 12],
 [13, 14, 15, 16]]

输出:

[[3,  4,  8, 12],
 [2, 11, 10, 16],
 [1,  7,  6, 15],
 [5,  9, 13, 14]]

(奇怪的空格是将数字对齐在漂亮的列中)

矩阵的外部“环”逆时针旋转2,而内部右环也旋转2。在这个矩阵中,只有两个环。

带有1个“环”的示例:

2
[[1, 2],
 [3, 4],
 [5, 6]]

应该输出:

[[4, 6],
 [2, 5],
 [1, 3]]

您面临的挑战是接受一个矩阵和一个整数R,并在R旋转后输出翻译后的版本。

下图表示4x5矩阵的旋转: 在此处输入图片说明

限制条件:

  • 2 ≤ M, N ≤ 100,其中M和N是矩阵的尺寸。保证M和N的最小值是偶数。
  • 1 ≤ R ≤ 80,其中r是转数。
  • 矩阵将永远只包含正整数。
  • 价值并不总是截然不同的。
  • 输入应始终为2D数组(如果您不能将运行时输入作为2D数组,则只需寻找另一种获取输入的方法)。

另一个测试用例,具有不同的值:

1
[[1, 1],
 [2, 2],
 [3, 3]]

输出:

[[1, 2],
 [1, 3],
 [2, 3]]

这是,所以最短的答案会成功!





4
@ceasedtoturncounterclockwis您的名字对这个挑战非常具有讽刺意味……
HyperNeutrino

1
[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 16], [5, 9, 13, 14]]16突然重复我想这应该是:[[3, 4, 8, 12], [2, 11, 10, 16], [1, 7, 6, 15], [5, 9, 13, 14]]
克里斯多夫(Christoph)

Answers:



5

八度,210字节

function M=F(M,R);f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];t=angle(f([x y]=size(M))'+f(y)*i);B=!!M;B(2:x-1,2:y-1)=0;d=bwdist(B,'ch');[~,I]=sortrows([d(:) t(:)]);for k=0:max(d(:));M(h)=shift(M(h=I(d(I)==k)),R);end

在Octave Online上尝试!

非高尔夫版本:

function M=F(M,R)
    [x y]=size(M);
    f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2];
    t=angle(f(x)'+f(y)*i);
    B=!!M;
    B(2:x-1,2:y-1)=0;
    d=bwdist(B,'chessboard');
    [~,I]=sortrows([d(:) t(:)]);
    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end
end
R=2;
M=randi(10,4,7)
F(M,R)

说明:

f=@(z)[-z/2:-1 !eye(!!mod(z,2)) 1:z/2]; 

一个获得数字并生成一个范围为输入4的有序和居中的函数(偶数) -2 -1 1 2
为输入5(奇数)生成的生成-2.5 -1.5 0 1 2
仅生成应排序和居中的

f(x)'+f(y)*i    

从范围生成的复杂矩阵

(-2,-2.5) (-2,-1.5) (-2,0) (-2,1) (-2,2)
(-1,-2.5) (-1,-1.5) (-1,0) (-1,1) (-1,2)
(1,-2.5)  (1,-1.5)  (1,0)  (1,1)  (1,2)
(2,-2.5)  (2,-1.5)  (2,0)  (2,1)  (2,2)

t=angle(f(x)'+f(y)*i);                    

将直角坐标转换为极坐标和返回角,以便针对每个环角逆时针排序

-2.25  -2.50  3.14  2.68  2.36
-1.95  -2.16  3.14  2.36  2.03
-1.19  -0.98  0.00  0.79  1.11
-0.90  -0.64  0.00  0.46  0.79


B=!!M;
B(2:x-1,2:y-1)=0;

生成以下矩阵

1   1   1   1   1
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

d=bwdist(B,'chessboard');

使用棋盘距离计算B的距离变换以生成环形索引

0   0   0   0   0
0   1   1   1   0
0   1   1   1   0
0   0   0   0   0               

对于6 * 7矩阵,我们将具有以下矩阵

0   0   0   0   0   0   0
0   1   1   1   1   1   0
0   1   2   2   2   1   0
0   1   2   2   2   1   0
0   1   1   1   1   1   0
0   0   0   0   0   0   0   

[~,I]=sortrows([d(:) t(:)]);

字典顺序首先根据环索引排序,然后再按角度顺序排序(返回排序元素的索引)

    for k=0:max(d(:))
        M(h)=shift(M(h=I(d(I)==k)),R);
    end

最后循环移动每个环。


4

Python 3中,292个 288字节

_=eval
a=input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=range
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print(_("g("*b+"a"+")"*b)[::-1])

接受输入,其中已删除换行符,但在将其旋转的增量数量之后留有空格。

说明:

不必按照OP的建议将矩阵建模为一系列同心环,而是可以将矩阵划分为四个区域,元素在单个旋转中向上,向下,向右或向左移动。这是长字符串评估的目的f:确定每种i,j组合落入哪个区域。然后,将其结果在中查询两次l,给出i,j下一步必须旋转到位的元素。功能g执行所有的这并形成单一的步骤之后的新的矩阵然后由evaling含有嵌套函数调用的表示所生成的字符串重复调用。

最初制作时,我不小心使矩阵顺时针旋转,而不是逆时针旋转。我没有进行适当的修复,而是添加了两个策略性放置的副本,[::-1]以在旋转之前和之后反转矩阵。这些可能被压缩到280 276字节,但是我太懒了。

此外,这是一个稍长的Python 2程序的快速未经测试的移植,如果不能正常工作,请原谅我。无论如何,这是Python 2代码:

_=eval
a=raw_input().split()
b,a=int(a[0]),_("".join(a[1:]))[::-1]
c=len(a)
d=len(a[0])
e=xrange
f="int((i>=j and i+j<c-1)|2*(i>=c/2and i+d>j+c)|3*(i<c/2and i+j<d))"
l=[-1,1,0,0],[0,0,1,-1]
g=lambda x:[[x[i+l[0][_(f)]][j+l[1][_(f)]]for j in e(d)]for i in e(c)]
print _("g("*b+"a"+")"*b)[::-1]

编辑:or|两次替换掉4个字节。and不幸的是,我们无能为力。


欢迎来到PPCG!不错的第一篇文章!
HyperNeutrino

有趣的故事-在今天的我的高中乐队中,我们学到了一种编队,每个人都在类似这个问题的同心矩形“环”中运动,我立即想到了这个答案。
艾丹·皮尔斯

1

Perl中,330个 328字节

sub f{($r,$m)=@_;$h=@m=@$m;for$s(0..(($w=$#{$m[0]})<--$h?$w:$h)/2-.5){@_=(@{$m[$s]}[@x=$s..($x=$w-$s)],(map$m[$_][$x],@y=1+$s..($y=$h-$s)-1),reverse(@{$m[$y]}[@x]),(map$m[$h-$_][$s],@y));push@_,shift
for 1..$r;@{$m[$s]}[@x]=map shift,@x;$m[$_][$x]=shift for@y;@{$m[$y]}[@x]=reverse map shift,@x;$m[$h-$_][$s]=shift for@y}@$m=@m}

在Ideone上尝试一下

取消高尔夫:

sub f {
    my ($r, $m) = @_;

    my @m = @$m;
    my $h = $#m;
    my $w = @{$m[0]} - 1;
    my $c = (($w < $h ? $w : $h) + 1) / 2 - 1;

    for my $s (0 .. $c) {
        my $x = $w - $s;
        my $y = $h - $s;
        my @x = $s .. $x;
        my @y = $s + 1 .. $y - 1;

        # One circle.
        @_ = (@{$m[$s]}[@x],
              (map { $m[$_][$x] } @y),
              reverse(@{$m[$y]}[@x]),
              (map { $m[$h - $_][$s] } @y));

        # Circular shift.
        push(@_, shift(@_)) for 1 .. $r;

        @{$m[$s]}[@x] = map { shift(@_) } @x;
        $m[$_][$x] = shift(@_) for @y;
        @{$m[$y]}[@x] = reverse(map { shift(@_) } @x);
        $m[$h - $_][$s] = shift(@_) for @y;
    }

    @$m = @m;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.