Hapus nol di sekitarnya dari array 2d


40

Ini adalah versi 2 dimensi dari pertanyaan ini .

Diberikan array / matriks 2 dimensi yang tidak kosong yang hanya mengandung bilangan bulat non-negatif:

[0000000010000010011100000]

Keluarkan array dengan nol di sekitarnya dihapus, yaitu subarray berdekatan yang terbesar tanpa nol sekitarnya:

[010001111]

Contoh:

[0000000010000010011100000][010001111]
Input:
[[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]]

Output:
[[0, 1, 0], [0, 0, 1], [1, 1, 1]]

[00000003000005000000][003000500]
Input:
[[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]]

Output:
[[0, 0, 3], [0, 0, 0], [5, 0, 0]]

[123456789][123456789]
Input:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Output:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

[000000000000][]
Input:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

Output:
[]

[000011110000][1111]
Input:
[[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]

Output:
[[1, 1, 1, 1]]

[010001000100][111]
Input:
[[0, 1, 0, 0], [0, 1, 0, 0], [0, 1, 0, 0]]

Output:
[[1], [1], [1]]

[111112311111][111112311111]
Input:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

Output:
[[1, 1, 1, 1], [1, 2, 3, 1], [1, 1, 1, 1]]

3
@MattH Tidak ada yang sulit dalam bahasa non-esoterik. :)Sulit membuatnya pendek.
user202729

1
Bisakah kita memberikan output falsey bukan matriks kosong, untuk test case terakhir?
sundar - Reinstate Monica

1
Juga, jika output dapat berupa matriks non-kuadrat, harap tambahkan test case untuk itu.
sundar - Reinstate Monica

1
Sebuah test case yang melanggar kiriman saya sebelumnya: [[0, 0, 0, 0], [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]](hasilnya memiliki lebar / tinggi 1)
Conor O'Brien

1
Hai, mungkinkah menambahkan kotak uji
[111112311111]
Peluruhan Beta

Jawaban:



39

Bahasa Wolfram (Mathematica) , 42 byte

#&@@CellularAutomaton[{,{},0{,}},{#,0},0]&

Cobalah online!

Automata seluler memang jawaban untuk kehidupan , alam semesta , dan segalanya . 1

Bagaimana?

CellularAutomatonmenerima array input dan nilai latar belakang opsional. Dengan demikian, {#,0}menetapkan bahwa aturan otomat seluler harus diterapkan pada input, dengan asumsi latar belakang 0s.

Suatu hal yang rapi di sini adalah bahwa CellularAutomatontanaman output sehingga tidak ada batas sel latar hadir (karena jika tidak output terletak pada bidang yang tak terbatas).

Kode menerapkan aturan {Null, {}, {0, 0}}- menerapkan kepala Nullke 0-radius tetangga setiap sel (yaitu hanya pusat: sel itu sendiri) - tepat 0waktu. Hasil dari ini adalah input asli, tetapi dengan latar belakang dihapus (yaitu memotong sekitar 0s).


1. Lihat bytecount jawaban saya? ;)


6
Pelecehan bawaan yang bagus ... well Mathematica memiliki fitur bawaan, hanya saja tidak terpapar langsung.
user202729

3
Tidak ada referensi XKCD 505 ?
Buah Esolanging

+1 untuk Cellular Automata & the Ultimate Answer.
HighlyRadioactive

14

JavaScript (ES6), 98 byte

(a,z)=>(g=A=>A.slice(A.map(m=M=(r,i)=>M=(z?a:r).some(n=>z?n[i]:n)?1/m?i:m=i:M)|m,M+1))(a).map(z=g)

Cobalah online!

Bagaimana?

Untuk mengatasi kekurangan built-in zip , kami mendefinisikan fungsi g () yang dapat beroperasi pada baris atau kolom dari matriks input a [] , tergantung pada nilai flag global z .

g () mencari indeks minimum m dan indeks maksimum M dari baris yang tidak kosong (jika z tidak ditentukan) atau kolom tidak kosong (jika z ditentukan) dan mengembalikan potongan yang sesuaibaik dari matriks itu sendiri atau baris yang diberikan dari matriks.

Untuk meringkas:

  • pertama-tama kita menghapus baris dengan menjalankan g () pada matriks dengan z tidak terdefinisi
  • kami kemudian menghapus kolom dengan menggunakan g () pada setiap baris dengan z yang ditentukan, yang mengarah ke hal yang agak tidak biasa ini.map(z=g)

Berkomentar

(a, z) => (               // a[] = input matrix; z is initially undefined
  g = A =>                // g() = function taking A = matrix or row
    A.slice(              //   eventually return A.slice(m, M + 1)
      A.map(m = M =       //     initialize m and M to non-numeric values
        (r, i) =>         //     for each row or cell r at position i in A:
        M = (z ? a : r)   //       iterate on either the matrix or the row
        .some(n =>        //       and test whether there's at least one
          z ? n[i] : n    //       non-zero cell in the corresponding column or row
        ) ?               //       if so:
          1 / m ? i       //         update the maximum index M (last matching index)
                : m = i   //         and minimum index m (first matching index)
        :                 //       otherwise:
          M               //         let M (and m) unchanged
      ) | m,              //     end of map(); use m as the first parameter of slice()
      M + 1               //     use M+1 as the second parameter of slice()
    )                     //   end of slice()
  )(a)                    // invoke g() on the matrix with z undefined
  .map(z = g)             // invoke g() on each row of the matrix with z defined

2
Itu mengesankan.
Jack Hales

3
@Jek, Arnauld hidup dalam dimensi yang berbeda. Tetapi jika Anda sangat beruntung, sesekali Anda dapat menemukan trik yang dia lewatkan dan memposting solusi yang lebih pendek. Dalam prosesnya, Anda akan mengembangkan pemahaman yang sangat mendalam tentang JavaScript.
Rick Hitchcock

4
@RickHitchcock Saya tidak begitu pandai dalam pengenalan pola kode dan saya sering kehilangan banyak hal, bahkan jika saya pernah melihatnya sebelumnya. Dalam contoh khusus ini, saya fokus pada usabilitas g () dan melewatkan optimasi yang cukup jelas dalam cara memperbarui m dan M (-9 byte). Saya sepenuhnya setuju bahwa bermain golf kode adalah cara yang hebat (dan menyenangkan) untuk belajar banyak tentang seluk-beluk suatu bahasa.
Arnauld

7

Haskell , 62 61 byte

f.f.f.f
f=reverse.foldr(zipWith(:))e.snd.span(all(<1))
e=[]:e

Cobalah online!

foldr(zipWith(:))edengan e=[]:eadalah sedikit lebih pendektranspose , dan snd.span(all(<1))tetes daftar terkemuka nol dari daftar list. Seperti transposediikuti oleh reversepada daftar 2D sama dengan rotasi oleh 90 °, kode f.f.f.fhanya empat kali menjatuhkan daftar nol terkemuka dan memutar .




5

Brachylog , 24 22 20 19 byte

{s.h+>0∧.t+>0∧}\↰₁\

Cobalah online!

Output matriks hasil sebagai array array, atau false untuk output kosong.

(Terima kasih kepada @Fatalize untuk menyarankan predikat sebaris dan menghemat 1 byte.)

Penjelasan

Predikat 0 (Utama):

{...}     Define and call predicate 1 to remove all-zero rows
  \       Transpose the result
   ↰₁     Call pred 1 again, now to remove all-zero columns
     \    Transpose the result to have correct output orientation

Predikat 1:

?s.h+>0∧.t+>0∧
  .           output is
 s              a subsequence of the rows of
?              the input (implicit)
   h          also, output's head element (first row)
    +>0        has a sum > 0 (i.e. has at least one non-zero value)
       ∧.t+>0  and similarly the output's tail element (last row)
∧              (don't implicitly unify that 0 with the output)

Menulis inline predikat pertama adalah 1 byte pendek: {s.h+>0∧.t+>0∧}\↰₁\ . (Ini berlaku untuk hampir semua jawaban Brachylog, predikat pada baris baru benar-benar hanya diterapkan jika Anda ingin menulis hal-hal yang lebih mudah dibaca).
Fatalkan tanggal

@Formatisasi Terima kasih, diperbarui (akhirnya!). Saya tidak pernah berpikir tentang bagaimana sintaksis predikat inline merupakan definisi dan aplikasi predikat, cukup keren.
sundar - Reinstate Monica

5

R , 96 100 97 byte

function(m)m[~m,~t(m),drop=F]
"~"=function(x,z=seq(r<-rowSums(x)))z>=min(y<-which(r>0))&z<=max(y)

Cobalah online!

The ~helper mengambil vektor non-negatif dan kembali vektor dengan FALSEuntuk "eksterior" 0s vektor dan TRUEuntuk positif dan setiap "interior" 0s. Fungsi ini diterapkan pada jumlah baris dan kolom dari matriks input.

~dan ! gunakan perawatan parser R untuk operator.

Diperbaiki sesuai komentar @ DigEmAll, tetapi dengan beberapa byte di-golf-kan kembali dari @ Joe


1
Saya pikir Anda harus menambahkan drop=Fseperti yang saya lakukan, jika tidak 2 tes ini akan mengembalikan vektor daripada baris dan kolom: Coba online!
digEmAll

97 byte dengan drop=F. Masih di bawah satu ton!
J. Oh,

5

R , 89 79 byte

function(m,y=apply(which(m>0,T),2,range)){y[!1/y]=0;m[y:y[2],y[3]:y[4],drop=F]}

Cobalah online!

Terima kasih kepada @ngm untuk kode kasus pengujian, dan @ J.Apakah Anda telah menghemat 10 byte!

  • Saya harus menambahkan drop=Fparameter karena perilaku R default mengubah baris / col matriks tunggal menjadi vektor ...

Saya tidak melihat bahwa kode saya sebelumnya gagal semua kasus nol ... sekarang ini sayangnya sayangnya diperbaiki dengan lebih banyak byte :(
digEmAll

1
Saya berharap saya bisa memberi ini +1. Penggunaan fivenum yang sangat bagus.
JayCe

79 byte menggunakan rangedan mengubah indeksasi
J.

1
@ J. Aduh: jangkauan, tentu saja! ide bagus terima kasih!
digEmAll


3

Python 2 , 71 byte

Kembali dengan memodifikasi input. Daftar harus diberikan sebagai input.

def f(a):exec'while a and 1>sum(a[-1]):a.pop()\na[:]=zip(*a)[::-1]\n'*4

Cobalah online!


Python 2 , 77 byte

Ini juga memodifikasi input, tetapi berfungsi ....

def f(a):exec'while a and 1>sum(a[-1]):a.pop()\na=zip(*a)[::-1]\n'*4;return a

Cobalah online!





2

Sekam , 11 byte

!5¡(T0mo↔↓¬

Cobalah online!

Saya merasa beberapa byte dapat dicukur dengan memperpendek !5¡bagiannya.

Bagaimana itu bekerja

!5¡(

5th

mo↔↓¬

Petakan versi input saat ini dan: balikkan masing-masing, setelah menjatuhkan awalan terpanjang yang hanya terdiri dari nol (menjatuhkan awalan ini dilakukan dengan menggunakan Husk , yang merupakan fungsi yang memangkas jangka panjang elemen berurutan sejak awal daftar yang menghasilkan hasil yang benar ketika dijalankan melalui suatu fungsi, yaitu ¬, tidak logis).

T0

Transpose, ganti entri yang hilang dengan 0 .


2

Retina , 87 byte

/.\[(?!0,)/^+`\[0, 
[
/(?<! 0)]./^+`, 0]
]
\[(\[0(, 0)*], )+
[
(, \[0(, 0)*])+]|\[0]]
]

Cobalah online! Penjelasan:

/.\[(?!0,)/^+`

Hingga setidaknya satu baris tidak dimulai dengan nol ...

\[0, 
[

... hapus nol di depan dari setiap baris.

/(?<! 0)]./^+`

Hingga setidaknya satu baris tidak berakhir dengan nol ...

, 0]
]

... hapus nol tambahan dari setiap baris.

\[(\[0(, 0)*], )+
[

Hapus baris nol di depan.

(, \[0(, 0)*])+]|\[0]]
]

Hapus baris nol yang tertinggal, atau nol yang tersisa terakhir.


1
@RickHitchcock Formatnya sensitif, tambahkan spasi: Cobalah online!
Neil

2

Arang , 48 byte

F⁴«W∧θ¬Σ§θ±¹Σ⊟θ¿θ≔⮌E§θ⁰E觧θνλθ»⪫[]⪫Eθ⪫[]⪫ι, ¦, 

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Termasuk 15 byte untuk pemformatan. Penjelasan:

F⁴«

Ulangi 4 kali.

W∧θ¬Σ§θ±¹

Ulangi sementara array tidak kosong tetapi baris terakhirnya berjumlah nol ...

Σ⊟θ

Hapus baris terakhir dari array dan cetak baris dari panjang jumlahnya, yaitu tidak ada.

¿θ≔⮌E§θ⁰E觧θνλθ»

Jika array tidak kosong maka posisikan.

⪫[]⪫Eθ⪫[]⪫ι, ¦, 

Format array dengan baik untuk tampilan. (Output standar akan menjadi Iθgantinya.)


2

JavaScript, 144 140 129 127 byte

w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w))

140 -> 129 byte, terima kasih @Arnauld

Algoritma

  • Lakukan dua kali:
    • Temukan baris pertama yang bukan nol
    • Potong baris sebelumnya
    • Membalikkan
    • Temukan baris pertama yang bukan nol
    • Potong baris sebelumnya
    • Membalikkan
    • Mengubah urutan

f = w=>(t=w=>(q=(s=w=>w.some((r,j)=>r.find(e=>e,i=j))?w.slice(i).reverse():[[]])(s(w)))[0].map((e,j)=>q.map((e,i)=>q[i][j])))(t(w));

w1 = [[0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 1, 1], [0, 0, 0, 0, 0]];
w2 = [[0, 0, 0, 0], [0, 0, 0, 3], [0, 0, 0, 0], [0, 5, 0, 0], [0, 0, 0, 0]];
w3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
w4 = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]];

console.log(f(w1).join("\n"));
console.log(f(w2).join("\n"));
console.log(f(w3).join("\n"));
console.log(f(w4));


Anda dapat menyimpan 7 byte dengan menggunakan some/somealih-alih findIndex/finddan mengatur ulang deklarasi fungsi helper untuk menghilangkan tanda kurung di sekitar argumen fungsi utama (sekarang tunggal).
Arnauld

Saya pikir Anda dapat menyimpan 4 byte lagi dengan memiliki s kembali [[]]sehingga t dijamin untuk dapat beroperasi pada w[0].
Arnauld

2

Python 2 , 118 116 byte

f=lambda a,n=4,s=sum:n and f(zip(*a[max(i for i in range(len(a))if s(s(a[:i],()))<1):][::-1]),n-1)or(s(s(a,()))>0)*a

Cobalah online!


Disimpan:

  • -2 byte, terima kasih untuk shooqie

1
Anda dapat menyimpan dua byte dengan menetapkan s=sumdefinisi lambda
shooqie

2

PHP (> = 5.4), 200 194 186 184 byte

(-6 byte dengan mengembalikan nullbukan array kosong)

(-8 byte terima kasih kepada Titus )

(-2 byte dengan menelepon dengan referensi terima kasih kepada Titus )

function R(&$a){$m=$n=1e9;foreach($a as$r=>$R)foreach($R as$c=>$C)if($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}for(;$m<=$M;)$o[]=array_slice($a[$m++],$n,$N-$n+1);$a=$o;}

Cobalah online!

Bagaimana?

Menemukan indeks min dan maks untuk baris ( $m& $M) dan kolom ( $n& $N) dan menggantikan input dengan sub array dari $m,$nke $M,$N(ini adalah panggilan dengan referensi).


Hemat 6 byte denganif($C){$m>$r&&$m=$r;$M>$r||$M=$r;$n>$c&&$n=$c;$N>$c||$N=$c;}
Titus

... dan dua byte denganwhile($m<=$M)$o[]=array_slice($a[$m++],$n,$N-$n+1);
Titus

@Itus: Terima kasih atas tipsnya. Saya suka trik menggunakan &&dan ||dan saya yakin saya akan dapat menggunakan trik itu di tempat lain juga.
Night2

1
Anda dapat menyimpan dua byte lainnya dengan panggilan dengan referensi: $a=alih-alih return.
Titus

2

Oktaf, 48 49 byte

@(a)sparse(1-min([x y v]=find(a))+x,1-min(y)+y,v)

Cobalah online!

Temukan poin bukan nol dan atur ulang dalam matriks jarang baru.


@alephalpha Jawaban diperbarui!
rahnema1


2

J , 24 byte

(|.@|:@}.~0=+/@{.)^:4^:_

Cobalah online!

Penjelasan

(|.@|:@}.~0=+/@{.)^:4^:_
            +/                sum
              @               of
               {.             the first row
          0=                  is zero? (1 = true, 0 = false)
       }.~                    chop off that many rows from the front
 |.@|:@                       rotate by 90 deg (transpose then reverse)
(                )^:4         repeat this process 4 times (rotating a total of 360 deg)
                     ^:_      fixpoint - repeat until no change

2

Ruby , 73 63 byte

->a{4.times{_,*a=a while a[0]&.sum==0;a=a.reverse.transpose};a}

Cobalah online!

Edit: disederhanakan, juga versi sebelumnya jatuh untuk semua 0s

Bagaimana itu bekerja:

  • lakukan 4 kali:
    • hapus baris pertama saat ada baris pertama dan penuh dengan 0s
    • putar array searah jarum jam 90 °
  • kembalikan array

Tautannya benar, tetapi jawaban Anda di blok kode mengatakan &.sum<0bukan &.sum<1.
Conor O'Brien

@ ConorO'Brien, versi baru saya yang buruk tidak berfungsi untuk array kosong (nihil <1). Terima kasih atas
perhatiannya

1

Oktaf , 78 74 byte

function x=f(x)
for k=1:nnz(~x)*4,x=rot90(x);x=x(:,~~cumsum(any(x,1)));end

Cobalah online!

Penjelasan

Ini memutar matriks dengan 90derajat ( x=rot90(x)) beberapa kali ( for k=1:... end). Jumlah rotasi adalah kelipatan 4, sehingga matriks akhir memiliki orientasi asli. Secara khusus, jumlah rotasi adalah 4kali jumlah nol dalam matriks ( nnz(~x)*4).

Untuk setiap rotasi, jika ada satu atau lebih kolom di sebelah kiri yang hanya terdiri dari nol mereka dihapus ( x=x(:,~~cumsum(any(x,1)))).

Apa yang tersisa dari matriks setelah proses ini adalah keluaran oleh fungsi ( function x=f(x)).



1

PHP, 188 byte

function f(&$a){for($s=array_shift;!max($a[0]);)$s($a);for($p=array_pop;!max(end($a));)$p($a);for($w=array_walk;!max(($m=array_map)(reset,$a));)$w($a,$s);while(!max($m(end,$a)))$w($a,$p);}

panggilan dengan referensi.

kerusakan

// call by reference
function f(&$a)
{
    // while first row is all zeroes, remove it
    while(!max($a[0]))array_shift($a);
    // while last row is all zeroes, remove it
    while(!max(end($a)))array_pop($a);
    // while first column is all zeroes, remove it
    while(!max(array_map(reset,$a)))array_walk($a,array_shift);
    // while last column is all zeroes, remove it
    while(!max(array_map(end,$a)))array_walk($a,array_pop);
}


1

Python 2 , 86 byte

lambda a,l=1:a if l>4else([a.pop()for b in a if sum(a[-1])<1],f(zip(*a[::-1]),l+1))[1]

Cobalah online!

Mengambil daftar daftar, mengembalikan daftar tupel.

Penjelasan

Menyalahgunakan daftar pemahaman. Ini adalah kode yang diperluas yang setara:

def f(a,l=1):
    # after 4 rotations, the list is back in its original orientation, return
    if l > 4:
        return a
    else:
        # helper variable to store return values
        ret = []
        # "trim" all rows from "bottom" of list that only contain 0s
        # since we are always checking le that item in the list, don't need range(len(a))
        # since we are only removing at most one item per iteration, will never try to remove more than len(a) items
        # brackets surrounding generator force it to be consumed make a list, and therefore actually pop() list items
        ret.append([a.pop() for b in a if sum(a[-1]) < 1])
        # rotate the array, increase the number of rotations, and recursively call this function on the new array/counter
        ret.append(f(zip(*a[::-1]), l + 1)))
        # we only put both items in a list in order to stay in the one-line lambda format
        # discard the popped items and return the value from the recursive call
        return ret[1]

1

Japt -h , 23 , 11 byte

4Æ=sUb_dà z

Cobalah


Penjelasan

                :Implicit input of 2D-array U
4Æ              :Map the range [0,4)
   s            :  Slice U from
    Ub          :   The first index in U where
      _dà      :    Any element is truthy (not zero)
          z     :  Rotate 90 degrees
  =             :  Reassign to U for the next iteration
                :Implicitly output the last element
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.