Waspadalah terhadap tornado matriks!

27

Tornado matriks sama seperti tornado lainnya: ia terdiri dari benda-benda yang berputar di sekitar pusat. Dalam hal ini, elemen-elemen dari matriks bukan udara.

Berikut adalah contoh tornado matriks:

Tornado matriks beraksi

Pertama kita mulai dengan membagi matriks menjadi cincin persegi, setiap bagian terdiri dari elemen yang lebih jauh dari perbatasan dengan jarak yang sama. Bagian-bagian ini akan diputar searah jarum jam di sekitar tengah. Dalam tornado nyata, tingkat keparahan meningkat ke arah pusat, dan begitu juga langkah rotasi dalam tornado matriks: bagian terluar (yang merah) diputar oleh 1 langkah, yang berikutnya (kuning) diputar oleh 2, dan seterusnya di. Langkah rotasi adalah rotasi 90 ° di sekitar pusat.

Tugas:

Tugas Anda, jika Anda menerimanya, adalah menulis fungsi atau program yang mengambil sebagai input matriks kuadrat, menerapkan efek tornado padanya dan kemudian output matriks yang dihasilkan.

Memasukkan:

Input harus berupa matriks kuadrat pesanan di nmana n >= 1. Tidak ada asumsi yang dibuat tentang elemen-elemen matriks, mereka bisa apa saja.

Keluaran:

Matriks kuadrat dari urutan yang sama yang akan menjadi hasil menerapkan efek tronado ke matriks input.

Contoh:

Matriks pesanan n = 1:

[['Hello']]               ===>    [['Hello']]

Matriks pesanan n = 2:

[[1 , 2],                 ===>    [[5 , 1],
 [5 , 0]]                          [0 , 2]]

Matriks pesanan n = 5:

[[A , B , C , D , E],             [[+ , 6 , 1 , F , A],
 [F , G , H , I , J],              [- , 9 , 8 , 7 , B],
 [1 , 2 , 3 , 4 , 5],     ===>     [/ , 4 , 3 , 2 , C],
 [6 , 7 , 8 , 9 , 0],              [* , I , H , G , D],
 [+ , - , / , * , %]]              [% , 0 , 5 , J , E]]
ibrahim mahrir
sumber
Saya pikir Anda ingin mengklarifikasi bahwa rotasi adalah rotasi 90 °.
Erik the Outgolfer
Juga, sudahkah Anda mengambil tantangan ini dari tempat lain? Jika demikian, Anda harus memberikan atribusi.
Erik the Outgolfer
1
@EriktheOutgolfer 1) Saya sudah mengklarifikasi itu. 2) Tantangan ini adalah milikku.
ibrahim mahrir
4
@Giuseppe Tergantung di belahan mana Anda berada;)
Jo King
12
Pertama saya ingin mengatakan saya pikir ini adalah tantangan yang baik: kerja bagus! Tapi saya juga ingin menyambungkan poin ini karena saya pikir pilihan Anda untuk mengatakan bahwa itu bisa berupa jenis data apa pun meninggalkan tantangan Anda di tempat yang canggung. Demikian pula dengan pernyataan Anda tentang input menjadi daftar daftar, Anda telah membatasi bahasa yang dapat memecahkan masalah ini tanpa melakukan pekerjaan overhead. Saya pikir tantangannya lebih baik jika persyaratan ini santai. Saya harap Anda terus memposting tantangan bagus seperti ini! :)
FryAmTheEggman

Jawaban:

5

Python 3 , 100 byte

import numpy
def f(a):
 if len(a): a=numpy.rot90(a,axes=(1,0));a[1:-1,1:-1]=f(a[1:-1,1:-1]);return a

Cobalah online!

Aneesh Durg
sumber
8
Classic Python, hanya menjatuhkan a[1:-1,1:-1]=f(a[1:-1,1:-1])seperti itu adalah hal yang paling normal di dunia untuk secara langsung mendapatkan dan mengatur seluruh bagian dalam array 2 dimensi
ETHproduksi
1
@ ETHproductions Agar adil, bagian dari itu adalah sintaksis yang diwarisi darinumpy
Jo King
1
numpy.rot90(a,1,(1,0))lebih pendek 3 byte dan juga harus berfungsi.
Graipher
1
Apa gunanya TIO-link tanpa test case? ..: S Ini dia dengan (menjatuhkan spasi sebesar if len(a):a=...-1 byte).
Kevin Cruijssen
5

Arang , 44 byte

≔EθSθWθ«≔Eθ⮌⭆觧θνλθθM¹⁻¹Lθ≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Hanya bekerja pada kotak karakter karena standar I / O Charcoal tidak melakukan keadilan array normal. Penjelasan:

≔EθSθ

Baca kotak karakter.

Wθ«

Loop sampai kosong.

≔Eθ⮌⭆觧θνλθ

Putar itu.

θM¹⁻¹Lθ

Cetak, tapi kemudian pindahkan kursor ke satu persegi secara diagonal dari sudut aslinya.

≔E✂θ¹±¹¦¹✂κ¹±¹¦¹θ

Potong bagian luar dari array.

Neil
sumber
5

Jelly , 27 byte

J«þ`UṚ«Ɗ‘ịZU$LСŒĖḢŒHEƊƇṁµG

Cobalah online!

Saya pikir ini bisa menjadi jauh lebih pendek.

           Input: n×n matrix A.
J          Get [1..n].
 «þ`       Table of min(x, y).
    UṚ«Ɗ   min with its 180° rotation.

Now we have a matrix like: 1 1 1 1 1
                           1 2 2 2 1
                           1 2 3 2 1
                           1 2 2 2 1
                           1 1 1 1 1

‘ị          Increment all, and use as indices into...
     LС    List of [A, f(A), f(f(A)), …, f^n(A)]
  ZU$       where f = rotate 90°

Now we have a 4D array (a 2D array of 2D arrays).
We wish to extract the [i,j]th element from the [i,j]th array.

ŒĖ     Multidimensional enumerate

This gives us: [[[1,1,1,1],X],
                [[1,1,1,2],Y],
                ...,
                [[n,n,n,n],Z]]

ḢŒHEƊƇ     Keep elements whose Ḣead (the index) split into equal halves (ŒH)
           has the halves Equal to one another. i.e. indices of form [i,j,i,j]
           (Also, the head is POPPED from each pair, so now only [X] [Y] etc remain.)

ṁµG        Shape this like the input and format it in a grid.
Lynn
sumber
1
Anda mungkin bisa memasukkan µGfooter dan mengklaim bahwa kiriman Anda adalah 25.
Tn. Xcoder
5

Perl 6 , 78 73 72 byte

Terima kasih kepada nwellnhof untuk -5 byte!

$!={my@a;{(@a=[RZ] rotor @_: sqrt @_)[1..*-2;1..@a-2].=$!}if @_;@a[*;*]}

Cobalah online!

Blok kode rekursif yang mengambil array 2D yang diratakan dan mengembalikan array yang rata pula.

Penjelasan:

$!={      # Assign code block to pre-declared variable $!
    my@a; # Create local array variable a
   {
     (@a=[RZ]  # Transpose:
             rotor @_: sqrt @_;  # The input array converted to a square matrix
     )[1..*-2;1..@a-2].=$!  # And recursively call the function on the inside of the array
   }if @_;    # But only do all this if the input matrix is not empty
   @a[*;*]  # Return the flattened array
}
Jo King
sumber
Anda dapat menggunakan @a[*;*]alih-alih map |*,@auntuk meratakan array. (Alangkah baiknya jika ada cara untuk bekerja dengan array yang tidak rata dan subskrip multi-dimensi, tapi saya tidak bisa memikirkannya.)
nwellnhof
Tapi @a[1..*-2;1..@a-2].=$!berhasil.
nwellnhof
5

Oktaf , 86 81 byte

f(f=@(g)@(M,v=length(M))rot90({@(){M(z,z)=g(g)(M(z=2:v-1,z)),M}{2},M}{1+~v}(),3))

Cobalah online!

Saya sadar bahwa fungsi anonim rekursif bukan metode terpendek untuk melakukan sesuatu di Octave, tetapi mereka yang paling sejauh ini menyenangkan . Ini adalah fungsi anonim terpendek yang bisa saya buat, tapi saya ingin dikalahkan.

Penjelasan

Fungsi rekursif didefinisikan menurut ini jawaban oleh ceilingcat. q=f(f=@(g)@(M) ... g(g)(M) ...adalah struktur dasar dari fungsi anonim seperti itu, dengan g(g)(M)panggilan rekursif. Karena ini akan berulang tanpa batas, kami membungkus panggilan rekursif dalam array sel bersyarat:{@()g(g)(M),M}{condition}() . Fungsi anonim dengan daftar argumen kosong menunda evaluasi setelah kondisi telah dipilih (meskipun nanti, kita melihat bahwa kita dapat menggunakan daftar argumen untuk mendefinisikan z). Sejauh ini baru pembukuan dasar.

Sekarang untuk pekerjaan yang sebenarnya. Kami ingin fungsi kembali rot90(P,-1)dengan matriks P yang g(g)telah secara rekursif dipanggil pada bagian tengah M. Kami mulai dengan menetapkan z=2:end-1yang dapat kita sembunyikan dalam pengindeksan M. Dengan cara ini,M(z,z) memilih bagian tengah dari matriks yang perlu tornado lebih lanjut dengan panggilan rekursif. Bagian ini ,3memastikan bahwa rotasi searah jarum jam. Jika Anda tinggal di belahan bumi selatan, Anda dapat menghapus bit ini untuk -2 byte.

Kami kemudian melakukannya M(z,z)=g(g)M(z,z). Namun, nilai hasil operasi ini hanya bagian tengah yang dimodifikasi daripada seluruh Pmatriks. Karenanya, kami melakukan {M(z,z)=g(g)M(z,z),M}{2}yang pada dasarnya dicuri dari ini jawaban oleh Stewie Griffin.

Akhirnya, conditionhanya saja rekursi berhenti ketika input kosong.

Sanchises
sumber
+1 untuk belahan bumi selatan
ceilingcat
Saya belum mencoba membungkus kepala saya di sekitar rekursi dalam fungsi anonim, jadi saya tidak akan mencobanya, tapi saya ingin tahu apakah rekursi lebih pendek dari loop dalam yang satu ini .
Stewie Griffin
@StewieGriffin Saya akan melihat apa yang bisa saya lakukan :)
Sanchises
@StewieGriffin Ngomong-ngomong, silakan merasa tertantang untuk mengirim versi berbasis loop untuk tantangan ini di Octave. Saya benar-benar bertanya-tanya apakah Anda dapat mengalahkan pendekatan rekursif.
Sanchises
4

R , 87 byte

function(m,n=nrow(m)){for(i in seq(l=n%/%2))m[j,j]=t(apply(m[j<-i:(n-i+1),j],2,rev));m}

Cobalah online!

menggali semua
sumber
Apa boleh? Gambar menunjukkan panah searah jarum jam dan deskripsi di bawahnya menyatakan rotasi searah jarum jam ...
digEmAll
Saya harus membaca pertanyaan itu sepuluh kali dan tidak pernah melihatnya menyatakan searah jarum jam (karenanya komentar saya). Sayang.
Giuseppe
Eheh, ceritakan tentang itu ... Saya raja posting salah baca: D
digEmAll
1
Sayangnya matriks 1x1 tidak akan berfungsi (karena seq(0.5)mengembalikan 1 bukannya vektor kosong)
digEmAll
4

MATL , 25 24 23 22

t"tX@Jyq-ht3$)3X!7Mt&(

Cobalah online!

Mengindeks dalam MATL tidak pernah mudah, tetapi dengan bermain golf itu sebenarnya mengalahkan jawaban Jelly terbaik saat ini ...

t                       % Take input implicitly, duplicate.  
 "                      % Loop over the columns of the input*
   X@                   % Push iteration index, starting with 0. Indicates the start of the indexing range.
     Jyq-               % Push 1i-k+1 with k the iteration index. Indicates the end of the indexing range
         t              % Duplicate for 2-dimensional indexing.
  t       3$)           % Index into a copy of the matrix. In each loop, the indexing range gets smaller
             3X!        % Rotate by 270 degrees anti-clockwise
                7Mt&(   % Paste the result back into the original matrix. 

* Untuk n x nmatriks, program ini melakukan niterasi, sementara Anda benar-benar hanya perlu n/2rotasi. Namun, pengindeksan dalam MATL (AB) cukup fleksibel sehingga pengindeksan rentang yang mustahil hanyalah sebuah larangan. Dengan cara ini, tidak perlu membuang byte untuk mendapatkan jumlah iterasi yang tepat.

Sanchises
sumber
3

Python 2 , 98 byte

def f(a):
 if a:a=zip(*a[::-1]);b=zip(*a[1:-1]);b[-2:0:-1]=f(b[-2:0:-1]);a[1:-1]=zip(*b)
 return a

Cobalah online!

TFeld
sumber
3

K (ngn / k) , 41 39 38 byte

{s#(+,/'4(+|:)\x)@'4!1+i&|i:&/!s:2##x}

Cobalah online!

{ } berfungsi dengan argumen x

#x panjang dari x - ketinggian matriks

2##x dua salinan - tinggi dan lebar (diasumsikan sama)

s: ditugaskan kepada s untuk "bentuk"

!ssemua indeks matriks dengan bentuk s, misalnya !5 5adalah

(0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4
 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4)

Ini adalah matriks 2-baris (daftar daftar) dan kolomnya sesuai dengan indeks dalam matriks 5x5.

&/ minimum di atas dua baris:

0 0 0 0 0 0 1 1 1 1 0 1 2 2 2 0 1 2 3 3 0 1 2 3 4

i&|i:tetapkan ke i, balikkan ( |), dan bawa minima ( &) dengani

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

Ini adalah nomor cincin rata dari matriks 5x5:

4!1+ tambahkan 1 dan ambil modulo 4 sisanya

(+|:)adalah fungsi yang berputar dengan membalikkan ( |- kita perlu :memaksanya menjadi monadik) dan kemudian mentransposisi ( +- karena itu bukan kata kerja paling kanan di "kereta", kita tidak perlu a :)

4(+|:)\xmenerapkannya 4 kali x, menjaga hasil menengah

,/' ratakan masing-masing

+ mengubah urutan

( )@' indeks setiap nilai di sebelah kiri dengan setiap nilai di sebelah kanan

s# membentuk kembali ke s

ngn
sumber
2
Saya akan senang melihat penjelasan kode Anda
Galen Ivanov
1
@ GalenIvanov Tentu. Saya tidak berpikir saya bisa bermain golf ini lebih jauh, jadi saya mungkin mencoba menjelaskannya.
ngn
Terima kasih! Solusi Anda membuat saya ingin mulai belajar k (atau bahkan ngn / k :))
Galen Ivanov
@ GalenIvanov Karena terbiasa dengan J (dan APL?), Anda sudah setengah jalan di sana. K lebih kecil dan lebih sederhana, jadi saya akan sangat merekomendasikan mempelajarinya dan, tentu saja, saya senang mengobrol tentang hal itu di Orchard kapan saja. ngn / k hanya sebagian dari hal yang nyata tetapi saya bertujuan membuatnya cepat dan praktis.
ngn
Ya, saya pikir saya akan mencobanya.
Galen Ivanov
3

JavaScript (ES6), 99 byte

f=(a,k=m=~-a.length/2)=>~k?f(a.map((r,y)=>r.map(v=>y-m>k|m-y>k|--x*x>k*k?v:a[m+x][y],x=m+1)),k-1):a

Cobalah online!

Bagaimana?

W

m=W-12tx,y=maks(|y-m|,|x-m|)

tx,yW=5m=2

(2222221112210122111222222)

k=m(x,y)

tx,yk

sementara yang lain dibiarkan tidak berubah.

Ini sama dengan mengatakan bahwa sel tidak dirotasi jika kita memiliki:

(y-m>k) ATAU (m-y>k) ATAU (X2>k2) dengan X=m-x

yang merupakan tes yang digunakan dalam kode:

a.map((r, y) =>
  r.map(v =>
    y - m > k | m - y > k | --x * x > k * k ?
      v
    :
      a[m + x][y],
    x = m + 1
  )
)

Lalu kami menurun k dan mulai lagi, hingga k=-1 atau k=-3/2 (tergantung pada paritas W). Apa pun itu, hal itu memicu kondisi berhenti kami:

~k === 0
Arnauld
sumber
3

Jelly , 24 byte

ṙ⁹ṙ€
ḊṖ$⁺€ßḷ""ç1$ç-ZUµḊ¡

Cobalah online!

Saya pikir ini bisa menjadi jauh lebih pendek.

- Lynn

Erik the Outgolfer
sumber
Saya bertanya-tanya tentang solusi seperti ini! Itu ḷ""terlihat ajaib bagiku ^^ ingin menambahkan penjelasan?
Lynn
@ Lynn Hal terakhir yang saya harapkan adalah mendengar itu ḷ""ajaib. Hanya ḷ"dengan tambahan "... oh, ada sedikit kemungkinan bahwa ḷ"ini juga sesuatu yang saya "ciptakan" yang belum banyak digunakan karena seringkali dapat diganti dengan atom tunggal (tidak dalam kasus ini, seperti input juga bisa berisi 0).
Erik the Outgolfer
2

Haskell , 108 byte

e=[]:e
r=foldl(flip$zipWith(:))e
g!(h:t)=h:g(init t)++[last t]
f[x,y]=r[x,y]
f[x]=[x]
f x=r$(r.r.r.(f!).r)!x

Cobalah online!

Saya menggunakan transpose Laikoni dan memodifikasinya sedikit, untuk memutar array 90 °:

  e=[]:e;foldr(zipWith(:))e.reverse
 e=[]:e;foldl(flip$zipWith(:))e

Penjelasan

r memutar array sebesar 90 °.

(!)adalah fungsi tingkat yang lebih tinggi: "berlaku untuk pusat". g![1,2,3,4,5]adalah [1] ++ g[2,3,4] ++ [5].

f adalah fungsi tornado: casing dasar adalah ukuran 1 dan 2 (entah bagaimana 0 tidak bekerja).

Baris terakhir adalah di mana keajaiban terjadi: kita menerapkan r.r.r.(f!).rpada baris tengah xdan kemudian memutar hasilnya. Mari kita sebut mereka baris tengah M . Kami ingin recurse di tengah kolom dari M , dan untuk mendapatkan mereka, kita bisa memutar M dan penggunaan kemudian (f!). Kemudian kita gunakan r.r.runtuk memutar M kembali ke orientasi aslinya.

Lynn
sumber
2

Java 10, 198 192 byte

m->{int d=m.length,b=0,i,j;var r=new Object[d][d];for(;b<=d/2;b++){for(i=b;i<d-b;i++)for(j=b;j<d-b;)r[j][d+~i]=m[i][j++];for(m=new Object[d][d],i=d*d;i-->0;)m[i/d][i%d]=r[i/d][i%d];}return r;}

-6 byte terima kasih kepada @ceilingcat .

Cobalah online.

Penjelasan:

m->{                         // Method with Object-matrix as both parameter and return-type
  int d=m.length,            //  Dimensions of the matrix
      b=0,                   //  Boundaries-integer, starting at 0
      i,j;                   //  Index-integers
  var r=new Object[d][d];    //  Result-matrix of size `d` by `d`
  for(;b<=d/2;b++){          //  Loop `b` in the range [0, `d/2`]
    for(i=b;i<d-b;i++)       //   Inner loop `i` in the range [`b`, `d-b`)
      for(j=b;j<d-b;)        //    Inner loop `j` in the range [`b`, `d-b`)
        r[j][d+~i]=          //     Set the result-cell at {`j`, `d-i-1`} to:
          m[i][j++];         //      The cell at {`i`, `j`} of the input-matrix
    for(m=new Object[d][d],  //   Empty the input-matrix
        i=d*d;i-->0;)        //   Inner loop `i` in the range (`d*d`, 0]
      m[i/d][i%d]            //     Copy the cell at {`i/d`, `i%d`} from the result-matrix
        =r[i/d][i%d];}       //      to the replaced input-matrix
  return r;}                 //  Return the result-matrix as result

bpada dasarnya digunakan untuk menunjukkan di mana kita berada. Dan itu akan memutar cincin ini, termasuk semua yang ada di dalamnya satu kali searah jarum jam selama setiap iterasi.

Penggantian matriks input dilakukan karena Java adalah pass-by-reference, jadi hanya pengaturan r=makan berarti kedua matriks dimodifikasi ketika menyalin dari sel, menyebabkan hasil yang salah. Karena itu kami harus membuat Object-matrix baru (referensi baru), dan menyalin nilai di setiap sel satu-per-satu sebagai gantinya.

Kevin Cruijssen
sumber
1

MATLAB, 93 byte

function m=t(m),for i=0:nnz(m),m(1+i:end-i,1+i:end-i)=(rot90(m(1+i:end-i,1+i:end-i),3));end;end

Saya yakin ini bisa golf lagi entah bagaimana.

Penjelasan

function m=t(m),                                                                          end % Function definition
                for i=0:nnz(m),                                                       end;    % Loop from 0 to n^2 (too large a number but matlab indexing doesn't care)
                                                            m(1+i:end-i,1+i:end-i)            % Take the whole matrix to start, and then smaller matrices on each iteration
                                                      rot90(                      ,3)         % Rotate 90deg clockwise (anti-clockwise 3 times)
                               m(1+i:end-i,1+i:end-i)=                                        % Replace the old section of the matrix with the rotated one
Jacob Watson
sumber
1

C (gcc) , 128 118 115 byte

-15 byte dari @ceilingcat

j,i;f(a,b,w,s)int*a,*b;{for(j=s;j<w-s;j++)for(i=s;i<w-s;)b[~i++-~j*w]=a[i*w+j];wmemcpy(a,b,w*w);++s<w&&f(a,b,w,s);}

Cobalah online!

ay
sumber
1

Haskell, 274 byte

wadalah fungsi utama, yang memiliki tipe [[a]] -> [[a]]yang Anda harapkan.

Saya yakin pegolf Haskell yang lebih berpengalaman dapat memperbaiki ini.

w m|t m==1=m|0<1=let m'=p m in(\a b->[h a]++x(\(o,i)->[h o]++i++[f o])(zip(tail a)b)++[f a])m'(w(g m'))
p m|t m==1=m|0<1=z(:)(f m)(z(\l->(l++).(:[]))(r(x h(i m)):(p(g m))++[r(x f(i m))])(h m))
t[]=1
t[[_]]=1
t _=0
h=head
f=last
x=map
i=tail.init
g=x i.i
z=zipWith
r=reverse
AlexJ136
sumber
Anda mungkin ingin melihat tips kami untuk bermain golf di Haskell, mis. Menggunakan pelindung alih-alih persyaratan akan menghemat beberapa byte.
Laikoni