Kotak terbesar di array 2d

26

Memasukkan

Papan: Wadah 2D (matriks, daftar daftar, dll.) Dari huruf-huruf seperti:

  ["B", "C", "C", "C", "C", "B", "B", "C", "A", "A"],
  ["B", "A", "C", "B", "B", "A", "B", "B", "A", "A"],
  ["B", "C", "B", "C", "A", "A", "A", "B", "C", "B"],
  ["B", "B", "B", "A", "C", "B", "A", "C", "B", "A"],
  ["A", "A", "A", "C", "A", "C", "C", "B", "A", "C"],
  ["A", "B", "B", "A", "A", "C", "B", "C", "C", "C"],
  ["C", "B", "A", "A", "C", "B", "B", "C", "A", "A"]

Jika Anda memilih daftar daftar, Anda dapat mengasumsikan bahwa semua daftar panjangnya sama.

Aturan

  • Untuk membuat persegi panjang yang valid, Anda membutuhkan semua sudut persegi panjang dengan 'huruf' yang sama.
  • Contoh, lihat papan sampel dengan X di bawah. Anda dapat melihat 'X' pada (1,0) juga pada (4,0) juga pada (1,3) dan pada (4,3) maka Anda memiliki kotak [1,0,4,3] yang artinya dari (1,0) hingga (4,3):

Papan sampel dengan X :

  ["B", "X", "C", "C", "X", "B", "B", "C", "A", "A"],
  ["B", "A", "C", "B", "B", "A", "B", "B", "A", "A"],
  ["B", "C", "B", "C", "A", "A", "A", "B", "C", "B"],
  ["B", "X", "B", "A", "X", "B", "A", "C", "B", "A"],
  ["A", "A", "A", "C", "A", "C", "C", "B", "A", "C"],
  ["A", "B", "B", "A", "A", "C", "B", "C", "C", "C"],
  ["C", "B", "A", "A", "C", "B", "B", "C", "A", "A"]
  • Tujuannya adalah untuk menemukan persegi panjang atau salah satu dari persegi panjang dengan area terbesar, dihitung dengan (kanan-kiri + 1) * (bawah-atas + 1)
  • Jika ada beberapa persegi panjang dengan area maksimum yang sama, hasilkan salah satunya. Secara opsional, yang dengan (koordinat atas, koordinat kiri, koordinat kanan, koordinat bawah) terkecil secara leksikografis.
  • Persegi panjang harus memiliki tepi yang sejajar dengan tepi papan.
  • Setiap huruf adalah karakter ASCII yang dapat dicetak dari A hingga Z (keduanya termasuk).

Keluaran

Outputnya harus berupa posisi kiri-atas dan kanan-bawah dari sudut persegi panjang area terbesar. Untuk sampel "papan" pertama, kotak besar adalah kotak kuning:

masukkan deskripsi gambar di sini

Dan jawabannya harus:

[1, 1, 8, 4]

Contoh kasus uji kedua

Masukan dari:

["C", "D", "D", "D", "A", "A"],
["B", "D", "C", "D", "A", "A"],
["B", "D", "D", "C", "A", "C"],
["B", "D", "B", "C", "A", "C"]

Harus menghasilkan satu dari tiga daftar koordinat ini yang mengidentifikasi area enam persegi panjang:

[1, 0, 2, 2]
[1, 0, 3, 1]
[3, 2, 5, 3]

Pertanyaan ini diposting di Stack Overflow dengan judul: Bagaimana menemukan persegi panjang terbesar dalam array 2D yang dibentuk oleh empat sudut yang identik? dan dengan solusi JS kasar ini (saya dapat mengatakan "kasar" karena kode saya;):

Ok, ini posting pertama saya, tolong toleransi dengan saya. Saya akan mengubah semua yang Anda katakan untuk meningkatkan kuis.

danihp
sumber
7
Hai, selamat datang di PPCG! Ini tampaknya menjadi tantangan yang baik, tetapi tampaknya tidak memiliki kriteria kemenangan. Biasanya, posting di sini ditandai [kode-golf], yang berarti kode terpendek (dalam byte) menang.
Conor O'Brien
1
Saya pikir saya akan memberi tahu Anda bahwa kami memiliki kotak pasir yang dapat Anda gunakan untuk mendapatkan umpan balik tentang pertanyaan sebelum dikirim ke situs utama. Kotak pasir berguna bagi hampir semua orang di sini, tetapi terutama bagi pemula, yang mungkin tidak tahu semua aturan dan harapan yang kita miliki.
Wheat Wizard
2
Beberapa jawaban menampilkan koordinat dalam urutan penyortiran untuk persegi "pertama" (yaitu, atas, kiri, bawah, kanan) alih-alih (kiri, atas, kanan, bawah) seperti yang terlihat dalam contoh Anda. Apakah ini ok?
nimi
2
Format keluaran yang kurang ketat biasanya mendorong lebih banyak jawaban, jadi sesuatu seperti juga ((left,top),(right,bottom))harus baik-baik saja. Saya menghapus jawaban dan jawaban saya lagi ketika pertanyaan benar-benar disempurnakan.
Angs
1
Tentu, Jika Anda akan menerima jawaban itu harus keseluruhan terpendek, ini adalah bagaimana kebanyakan orang menyukai hal-hal yang dilakukan di situs. Namun tidak ada konsekuensi untuk tidak melakukannya. Ada juga pendapat yang berkembang bahwa menerima jawaban akan merusak situs. Saya berpendapat demikian, dan karenanya saya tidak pernah menerima jawaban atas tantangan saya. Apa yang Anda lakukan terserah Anda.
Wheat Wizard

Jawaban:

6

Python 2 , 148 130 byte

lambda x,e=enumerate:min(((a-c)*(d-b),b,a,d,c)for a,y in e(x)for c,k in e(x)for b,g in e(y)for d,h in e(y)if g==h==k[b]==k[d])[1:]

Cobalah online!

ovs
sumber
Hai @ovs, apakah untuk Anda dan merepotkan jika saya mengubah aturan untuk mencari area menjadi: (x2-x1 + 1) × (y2-y1 + 1) seperti yang disarankan Angs?
danihp
Saya ingin melonggarkan beberapa aturan untuk mendorong lebih banyak jawaban. Bisakah saya?
danihp
@danihp Silakan. Ini tidak membatalkan jawaban saya, kan?
Ovs
Tidak, jawaban Anda benar! Bagus.
danihp
5

Retina , 163 162 byte

Lw$`(?<=(.*\n)*((.)*))(?=(.))((.)*(?<=(.*))\4)((.*\n)*((?>(?<-3>.)*)(?=\4)(?>(?<-6>.)*))\4)?
$.7,$#1,$.2,-$.($5$#9*$5),$.2,$#1,$.7,$.($#1*_$#9*
4{N`
)m`^.*?,

0G`

Cobalah online! Sunting: Disimpan 1 byte karena trailing yang )cocok dengan $.(itu implisit. Penjelasan:

Lw$`(?<=(.*\n)*((.)*))(?=(.))((.)*(?<=(.*))\4)((.*\n)*((?>(?<-3>.)*)(?=\4)(?>(?<-6>.)*))\4)?

Ekspresi reguler ini cocok dengan persegi panjang. Kelompoknya adalah sebagai berikut: 1) Baris atas (sebagai jumlah tangkapan) 2) Kolom kiri (panjang) 3) Penyeimbangan untuk memastikan sudut kiri sejajar 4) Huruf untuk sudut 5) Lebar + 1 (panjang) 6) Penyeimbang untuk memastikan sudut kanan sejajar 7) Kolom kanan (panjang) 8) tidak digunakan 9) Tinggi (sebagai jumlah tangkapan). The wMemastikan opsi yang semua lebar kemungkinan persegi panjang yang cocok untuk masing-masing atas diberikan sudut kiri. The $pilihan daftar hasil menggunakan pola substitusi berikut.

$.7,$#1,$.2,-$.($5$#9*$5),$.2,$#1,$.7,$.($#1*_$#9*

Substitusi adalah sebagai berikut: Kolom kanan, baris atas, kolom kiri, negasi luas persegi panjang (secara harfiah dihitung sebagai panjang pengulangan string lebar sebanyak satu kali lebih tinggi daripada jumlah kali), kolom kiri , baris atas, kolom kanan, diikuti oleh ekspresi yang mengevaluasi ke baris bawah (tangkapan akan menelan biaya 12 byte plus saya sudah kehabisan variabel satu digit). Empat tangkapan pertama mewakili urutan pengurutan berdasarkan prioritas. Saat Retina mengurutkan secara stabil, pengurutan multikolom dapat dibuat dengan mengurutkan berdasarkan setiap kolom pengurutan dari paling tidak ke prioritas terbesar. (Area harus disortir dalam urutan menurun, sehingga jenis string tunggal tidak dapat digunakan.)

4{N`

Empat jenis numerik kemudian dilakukan.

)m`^.*?,

Kolom sortir kemudian dihapus setelah setiap sortir.

0G`

Karenanya entri pertama adalah sekarang hasil yang diinginkan.

Catatan: Pembatasan pada pilihan persegi panjang dari suatu daerah sejak itu telah rileks dan versi 144 -byte 144 berikut ini lebih memilih yang lebih luas daripada persegi panjang yang lebih tinggi:

Lw$`(?<=(.*\n)*((.)*))(?=(.))((.)*(?<=(.*))\4)((.*\n)*((?>(?<-3>.)*)(?=\4)(?>(?<-6>.)*))\4)?
-$.($5$#9*$5);$.2,$#1,$.7,$.($#1*_$#9*
N`
0G`
.*;

Cobalah online!

Neil
sumber
Gagal persyaratan lexicographical-min (coba test case yang saya tambahkan ke OP misalnya) (mungkin juga output bisa dalam urutan yang salah ??) TIO
Jonathan Allan
(... yeah, dua nilai pertama dalam output adalah cara yang salah menurut saya)
Jonathan Allan
Saya hanya melonggarkan beberapa batasan (persyaratan lexicographical-min). Saya harap tidak menjadi masalah bagi Anda.
danihp
... sekarang ini perlu mencocokkan garis dan poin.
Jonathan Allan
Memperbaiki urutan leksikografis menelan biaya 20 byte :-( dan saya perhatikan bahwa perhitungan area berubah, yang harganya 2 byte lagi, tapi saya tidak tahu apa artinya @JonathanAllan tentang poin.
Neil
4

Jelly , (27?)  29  28 byte

27 jika pengindeksan berbasis 1 diizinkan - hapus jejak

Fṙ1s2;Uœị³EaZI‘P
ZLpLŒċÇÞṪF’

Program lengkap.

Cobalah online! (atau lihat test case lainnya )

Bagaimana?

Fṙ1s2;Uœị³EaZI‘P - Link 1, areaOrZero: list of pairs [[b,l],[t,r]]
F                - flatten the input                 [b,l,t,r]
 ṙ1              - rotate left one                   [l,t,r,b]
   s2            - split into twos                   [[l,t],[r,b]]
      U          - upend the input                   [[l,b],[r,t]]
     ;           - concatenate                       [[l,t],[r,b],[l,b],[r,t]]
         ³       - program's input
       œị        - multidimensional index into
          E      - all equal?                       X
            Z    - transpose the input              [[b,t],[l,r]]
           a     - logical AND (vectorises)         (if not X we now have [[0,0],[0,0]]
             I   - incremental differences          [t-b,r-l] (or [0,0] if not X)
              ‘  - increment (vectorises)           [t-b+1,r-l+1] (or [1,1] if not X)
               P - product                          area (or 1 if not X)

ZLpLŒċÇÞṪF’ - Main link: list of lists
Z           - transpose the input
 L          - length
   L        - length of the input
  p         - Cartesian product
    Œċ      - pairs with replacement
       Þ    - (stable) sort by:
      Ç     -   last link (1) as a monad
        Ṫ   - tail (note that the rightmost pre-sort represents the bottom-right 1x1
            -       so cannot be superseded by a non-matching rectangle)
         F  - flatten
          ’ - decrement (vectorises) (to get to 0-based indexing)
Jonathan Allan
sumber
4

Perl 6 , 83 73 byte

{([X] (^$^a[0]X ^$a)xx 2).max:{[eq] $a[.[*;1];.[*;0]]and[*] 1 X-[Z-] $_}}

Cobalah online!

Mengembalikan daftar daftar ((x0 y0) (x1 y1)).

Penjelasan

{
  ([X]                   # Cross product of corner pairs.
    (^$^a[0]             # Range of x coords.
     X                   # Cross product of coords.
     ^$a                 # Range of y coords.
    )xx 2                # Duplicate list.
  ).max:                 # Find maximum of all ((x0 y0) (x1 y1)) lists
  {                      # using the following filter.
    [eq]                 # All letters equal?
      $a[.[*;1];.[*;0]]  # Multidimensional subscript with y and x coord pairs.
    and                  # Stop if false.
    [*]                  # Multiply
      1 X-[Z-] $_        # for each axis 1 - (c0 - c1) == c1 - c0 + 1.
  }
}
nwellnhof
sumber
3

Haskell , 144 byte

import Data.Array
o=assocs
f r=snd$maximum[((c-a+1)*(d-b+1),[a,b,c,d])|((a,b),x)<-o r,((c,d),y)<-o r,x==y,r!(a,d)==r!(c,b),x==r!(a,d),a<=c,b<=d]

Cobalah online!

Angs
sumber
Anda dapat menghapus b<=d, selama Anda menyimpannya a<=c.
Wheat Wizard
@ovs sebenarnya itu tidak akan berfungsi baik (lihat contoh saya menambahkan TIO )
Jonathan Allan
@nimi: Saya bisa berargumen bahwa itu hanya masalah mentransposisi input.
Angs
Tidak masalah bagi saya. Anda dapat mengatur ulang input.
danihp
3

Jelly , 24 byte

XLṭLp`€p/⁺œị€EɗÐfI‘PɗÞ0Ṫ

Cobalah online!

terbukti bermanfaat.

Format output: [atas, bawah], [kiri, kanan] . Pengindeksan 1.

pengguna202729
sumber
3

JavaScript (ES6), 121 byte

-1 byte terima kasih kepada @ l4m2
-1 byte terima kasih kepada @tsh
+2 byte untuk mematuhi aturan penilaian persegi panjang baru

Mengambil input sebagai matriks string. Mengembalikan koordinat terindeks 0: [x0, y0, x1, y1] .

a=>a.map(b=(r,y)=>r.map((v,x)=>a.map((R,Y)=>R.map((V,X)=>V+R[x]+r[X]!=v+v+v|(A=(x+~X)*(y+~Y))<b||(o=[x,y,X,Y],b=A)))))&&o

Cobalah online!

Arnauld
sumber
a=>a.map(b=(r,y)=>r.map((v,x)=>a.map((R,Y)=>R.map((V,X)=>V+R[x]+r[X]!=v+v+v|(A=(X-x)*(Y-y))<=b||(o=[x,y,X,Y],b=A)))))&&o
l4m2
Jika ada beberapa persegi panjang dengan area maksimum yang sama, hasilkan salah satunya ; mungkin (A=...)<=b-> (A=...)<b?
tsh
@ tsh Itu sekarang memang aman. Terima kasih!
Arnauld
1

Java 8, 208 205 byte

m->{int r=0,R[]={},i=m.length,j,y,z,u,t,T;for(;i-->0;)for(j=m[i].length;j-->0;)for(y=i*j;y-->0;)if((T=m[i][j])==m[u=y/j][z=y%j]&T==m[i][z]&T==m[u][j]&r<(t=(i-u)*(j-z))){r=t;R=new int[]{z,u,j,i};}return R;}

Pasti bisa bermain golf .. Sekarang saya menggunakan pendekatan yang paling jelas menggunakan empat tiga bersarang untuk-loop.

-3 byte berkat @ceilingcat yang menggabungkan loop bagian dalam baris dan kolom menjadi satu loop.

Penjelasan:

Cobalah online.

m->{                         // Method with char-matrix parameter and int-array return-type
  int r=0,                   //  Largest area found, starting at 0
      R[]={},                //  Result coordinates, starting empty
      i=m.length,j,          //  x,y indices of the first corner
      y,z,                   //  x,y indices of the second corner
      u,t,T;                 //  Temp integers to reduce bytes
  for(;i-->0;)               //  Loop `i` over the rows
    for(j=m[i].length;j-->0;)//   Inner loop `j` over the columns
      for(y=i*j;y-->0;)      //    Inner loop over the rows and columns
        if((T=m[i][j])==m[u=y/j][z=y%j]
                             //      If the values at coordinates [i,j] and [y,z] are equal
           &T==m[i][z]       //      as well as the values at [i,j] and [i,z]
           &T==m[u][j]       //      as well as the values at [i,j] and [y,j]
           &r<(t=(i-u)*(j-z))){
                             //      And the current area is larger than the largest
          r=t;               //       Set `r` to this new largest area
          R=new int[]{z,u,j,i};}
                             //       And save the coordinates in `R`
  return R;}                 //  Return the largest rectangle coordinates `R`
Kevin Cruijssen
sumber