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 행렬의 회전은 다음 그림으로 표시됩니다. enter image description here

제약 사항 :

  • 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

답변:



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

파이썬 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의 제안에 따라 일련의 동심 고리로 매트릭스를 모델링하는 대신 단일 회전 동안 요소가 위, 아래, 오른쪽 또는 왼쪽으로 이동하는 4 개의 영역으로 나눌 수 있습니다. 이것은 긴 평가 문자열의 목적입니다 . fi,j조합에 속하는 영역을 결정 합니다. 그런 다음 그 결과가에서 두 번 조회 되어 다음 단계에서 l회전해야하는 요소를 제공합니다 i,j. 함수g 모든 작업을 수행하고 단일 단계 후에 새 행렬을 형성하는 함수는 중첩 된 함수 호출의 표현을 포함하는 생성 된 문자열을 회피하여 반복적으로 호출됩니다.

원래 이것을 만들었을 때 실수로 매트릭스를 시계 반대 방향이 아닌 시계 방향으로 회전 시켰습니다. 적절한 수정을하는 대신 [::-1]회전 전후에 매트릭스를 뒤집기 위해 전략적으로 배치 된 두 개의 복사본을 추가했습니다 . 이것들은 아마 ~ 280 276 바이트 로 골프를 칠 수는 있지만 그렇게하기에는 너무 게으르다.

또한 이것은 약간 더 긴 Python 2 프로그램에서 테스트되지 않은 빠른 포트이므로 제대로 작동하지 않으면 용서하십시오. 어쨌든 파이썬 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]

편집 : 대체하여 4 바이트 오프 Golfed or|두 번. and불행히도 도움을 줄 수 없습니다.


PPCG에 오신 것을 환영합니다! 좋은 첫 포스트!
HyperNeutrino

재미있는 이야기 – 실제로 오늘날 고등학교 마칭 밴드에서 우리는이 질문과 비슷한 동심의 사각형 고리로 움직이는 대형을 배웠고, 나는 즉시이 답을 생각했습니다.
Aidan F. Pierce

1

펄, 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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.