หมุนเมทริกซ์ 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 คือจำนวนรอบการหมุน
  • เมทริกซ์จะมีจำนวนเต็มบวกเท่านั้น
  • ค่าไม่แตกต่างกันเสมอ
  • อินพุตควรเป็นอาร์เรย์ 2 มิติเสมอ (หากคุณไม่สามารถรับข้อมูลรันไทม์เป็นอาร์เรย์ 2 มิติได้คุณจะต้องหาวิธีอื่นในการรับอินพุต)

อีกกรณีทดสอบที่มีค่าไม่แตกต่างกัน:

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

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 เราสามารถแบ่งมันออกเป็นสี่ส่วนซึ่งองค์ประกอบนั้นเคลื่อนที่ขึ้นลงซ้ายขวาหรือซ้ายในระหว่างการหมุนครั้งเดียว นี่คือจุดประสงค์ของสตริง eval-ed ที่มีความยาวf: เพื่อกำหนดว่าแต่ละi,jภาคีจะรวมกันเป็นกลุ่มใด จากนั้นผลลัพธ์ของสิ่งนั้นจะถูกค้นหาสองครั้งlโดยให้องค์ประกอบที่ต้องหมุนเข้าสู่ตำแหน่งi,jในขั้นตอนถัดไป ฟังก์ชั่นgที่ทำทั้งหมดนี้และสร้างเมทริกซ์ใหม่หลังจากเรียกขั้นตอนเดียวซ้ำแล้วซ้ำอีกโดยการสร้างสตริงที่สร้างขึ้นซึ่งมีการแสดงการเรียกใช้ฟังก์ชันที่ซ้อนกัน

เมื่อฉันทำสิ่งนี้ในขั้นต้นฉันบังเอิญทำให้เมทริกซ์หมุนตามเข็มนาฬิกาแทนที่จะเป็นทวนเข็มนาฬิกา แทนที่จะทำการแก้ไขที่เหมาะสมฉันได้เพิ่มสำเนาสองชุดของกลยุทธ์[::-1]เพื่อย้อนกลับเมทริกซ์ก่อนและหลังการหมุน สิ่งเหล่านี้อาจจะสามารถเล่นกอล์ฟได้ถึง280 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]

แก้ไข: Golfed off 4 bytes โดยแทนที่orด้วย|สองครั้ง andอดไม่ได้ที่จะช่วย


ยินดีต้อนรับสู่ PPCG! โพสต์แรกที่ดี!
HyperNeutrino

เรื่องตลกจริง ๆ แล้วในโรงเรียนมัธยมวงดนตรีของฉันในวันนี้เราได้เรียนรู้รูปแบบที่ทุกคนเคลื่อนที่ใน "วง" รูปสี่เหลี่ยมผืนผ้าศูนย์กลางคล้ายกับคำถามนี้และฉันก็คิดถึงคำตอบนี้ทันที
Aidan F. Pierce

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

Ungolfed:

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.