2d dizisindeki en büyük dikdörtgen


26

Giriş

Tahta: Bir 2B konteyner (matris, listeler listesi, vb.):

  ["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"]

Bir liste listesi seçerseniz, tüm alt listelerin aynı uzunlukta olduğunu varsayabilirsiniz.

kurallar

  • Geçerli bir dikdörtgen yapmak için, aynı 'harf' ile tüm dikdörtgen köşelere ihtiyacınız vardır.
  • Örnek, örnek kartına X körüklü bakın. 'X' 'i (1,0)' da (4,0) 'de (1,3)' de ve (4,3) 'de görüyorsunuz. (1,0) ila (4,3):

X ile örnek kart :

  ["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"]
  • Amaç, dikdörtgeni veya en büyük alana sahip dikdörtgenlerden birini bulmaktır (sağ-sol + 1) * (alt-üst + 1)
  • Aynı maksimum alana sahip birden fazla dikdörtgen varsa, herhangi birini çıkartın. İsteğe bağlı olarak (üst koordinat, sol koordinat, sağ koordinat, alt koordinat) sözlüksel olarak en küçük olanı.
  • Dikdörtgenlerin, kartın kenarına paralel kenarları olmalıdır.
  • Her harf, A'dan Z'ye (ikisi de dahil) yazdırılabilir bir ASCII karakteridir.

Çıktı

Çıktı, en büyük alan dikdörtgen köşelerinin sol ve sağ aşağı konumlarında olmalıdır. İlk örnek “tahta” için büyük kare sarı olandır:

görüntü tanımını buraya girin

Ve cevap şöyle olmalı:

[1, 1, 8, 4]

İkinci bir örnek test davası

Bir giriş:

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

Bir alan altı dikdörtgenini tanımlayan bu üç koordinat listesinden birini vermelidir:

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

Bu soru, Taşma Taşması başlığında şöyle yazılmıştır: Dört köşeden oluşan 2B dizideki en büyük dikdörtgen nasıl bulunur? ve bu kaba JS çözümüyle ("kaba" diyebilirim çünkü kodum;):

Tamam, ilk görevim, lütfen bana karşı hoşgörülü ol. Testini geliştirmek için söylediğin her şeyi değiştireceğim.


7
Merhaba, PPCG'ye hoş geldiniz! Bu iyi bir meydan okuma gibi görünüyor, ancak herhangi bir kazanma kriteri yok gibi görünüyor. Tipik olarak, buradaki gönderiler [code-golf] olarak etiketlenir, yani en kısa kod (bayt cinsinden) kazanır.
Conor O'Brien,

1
Ana siteye gönderilmeden önce sorular hakkında geri bildirim almak için kullanabileceğiniz bir sanal alana sahip olduğumuzu size bildireceğimi düşündüm . Kum havuzu buradaki hemen hemen herkes için ama özellikle sahip olduğumuz tüm kuralları ve beklentileri bilemeyen yeni başlayanlar için kullanışlıdır.
Buğday Sihirbazı,

2
Bazı cevaplar, koordinatlarda, örneklerde görüldüğü gibi (sol, üst, sağ, alt) yerine "ilk" dikdörtgenin (yani, üst, sol, alt, sağ) sıralama düzenini verir. Bu tamam?
nimi

2
Daha az katı çıktı biçimleri genellikle daha fazla yanıtı teşvik eder, bu nedenle de böyle bir şey ((left,top),(right,bottom))iyi olmalı. Cevap tamamen silindiğinde cevaplarımı sildim ve tekrar cevapladım.
Angs,

1
Elbette, bir cevabı kabul edecekseniz, genel olarak en kısa olanı olmalıdır. Ancak bunu yapmamanın bir sonucu yok. Cevapları kabul etmenin siteye zararlı olduğu konusunda artan bir görüş de var . Bu görüşün içindeyim ve bu yüzden zorluklarıma cevapları asla kabul etmiyorum. Yaptığın şey sana kalmış.
Buğday Sihirbazı,

Yanıtlar:


6

Python 2 , 148 130 bayt

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:]

Çevrimiçi deneyin!


Merhaba @ovs, alanı belirlemek için kuralı değiştirdiğimde sizin için ve sakıncalıdır: (x2-x1 + 1) × (y2-y1 + 1) Angs'ın önerdiği gibi?
danihp

Daha fazla cevabı teşvik etmek için bazı kuralları gevşetmek isterim. Yapabilirmiyim?
danihp

@ danihp Devam edin. Bu benim cevabımı geçersiz kılmaz, değil mi?
ovs

Hayır, cevabın doğru! Güzel.
danihp

5

Retina , 163 162 bayt

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

0G`

Çevrimiçi deneyin! Düzenleme: arka Kaydedilen 1 bayt için )eşleşen $.(gizlidir. Açıklama:

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

Bu normal ifade, dikdörtgenlerle eşleşiyor. Gruplar aşağıdaki gibidir: 1) Üst sıra (yakalama sayısı olarak) 2) Sol sütun (uzunluk olarak) 3) Sol köşelerin hizalanmasını sağlamak için dengeleme 4) Köşeler için harf 5) Genişlik + 1 (uzunluk olarak) 6) Dengeleme Sağ köşelerin hizalanmasını sağlamak için 7) Sağ sütun (uzunluk olarak) 8) kullanılmamış 9) Yükseklik (yakalama sayısı olarak). w seçenek, her bir sol üst köşe için olası tüm dikdörtgen genişliklerinin eşleşmesini sağlar. $Seçenekler listeleri aşağıdaki değiştirme modelini kullanarak sonuçları.

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

Yer değiştirmeler aşağıdaki gibidir: Sağ sütun, üst satır, sol sütun, dikdörtgenin alanının ihmali (kelimenin tam anlamıyla genişlik dizesinin yükseklik sayısından bir kereden fazla tekrarlanması uzunluğu olarak hesaplanır), sol sütun , en üstteki satır, sağdaki sütun, ardından en alttaki satıra değer veren bir ifade (bir yakalamanın maliyeti 12 bayta mal olur, artı tek basamaklı değişkenlerden kaçarım). İlk dört yakalama, öncelik sırasına göre sıralama düzenini temsil eder. Retina istikrarlı bir şekilde sıralandıkça, her sıralama sütununa göre en az önceliğe göre sıralama yaparak çok sütunlu bir sıralama oluşturulabilir. (Alan azalan düzende sıralanmalıdır, bu nedenle tek bir string sıralama kullanılamaz.)

4{N`

Dört sayısal sıralama daha sonra gerçekleştirilir.

)m`^.*?,

Sıralama sütunu her sıralamadan sonra silinir.

0G`

Bu nedenle ilk giriş şimdi istenen sonuçtur.

Not: Belirli bir alanın dikdörtgen seçimine getirilen kısıtlama o zamandan beri gevşemiş ve 144 144 baytlık bir sürüm daha uzun boylu bir dikdörtgen yerine daha geniş bir alanı tercih etmektedir:

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

Çevrimiçi deneyin!


Sözlük-dakika gereksinimi başarısız olur (örneğin OP'ye eklediğim test örneğini deneyin) (belki çıktı yanlış sırada olabilir mi?) TIO
Jonathan Allan 19

(... evet, çıktıdaki ilk iki değer, bence yanlış yoldur)
Jonathan Allan

Sadece bazı kısıtlamaları gevşetdim (sözlük-dakika gereksinimi). Umarım senin için sorun olmaz.
danihp

... bunun şimdi çizgileri ve noktaları eşleştirmesi gerekecek.
Jonathan Allan

Noktaları hakkında araçlarını @JonathanAllan neyi lexicographical sipariş maliyetini 20 bayt Tespit :-( ve ben alan hesaplama başka 2 bayt mal olan değiştiğini farkettim, ama bilmiyorum.
Neil

4

Jelly , (27?)  29  28 bayt

27 1 tabanlı dizine izin verilirse - izlemeyi kaldır

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

Tam bir program.

Çevrimiçi deneyin! (veya diğerine bakın test durumuna bakın )

Nasıl?

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)

4

Perl 6 , 83 73 bayt

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

Çevrimiçi deneyin!

Bir liste listesi döndürür ((x0 y0) (x1 y1)) .

açıklama

{
  ([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.
  }
}

3

Haskell , 144 bayt

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]

Çevrimiçi deneyin!


Sen kaldırabilirsiniz b<=dsürece tutmak gibi a<=c.
Buğday Sihirbazı

@ovs aslında işe yaramayacak (da TIO eklediğim örneğe bakın )
Jonathan Allan

@ nimi: Bunun sadece girdiyi aktarmanın bir meselesi olduğunu iddia edebilirim.
Angs,

Benim için uygun. Girişi transpoze edebilirsiniz.
danihp


3

JavaScript (ES6), 121 bayt

@ L4m2
sayesinde -1 bayt -1tste +2 bayt sayesinde yeni dikdörtgen puanlama kuralına uyması için -1 bayt sayesinde

Bir dizge matrisi olarak girdiyi alır. 0 indeksli koordinatları döndürür: [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

Çevrimiçi deneyin!


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

Aynı maksimum alana sahip birden fazla dikdörtgen varsa, herhangi birini çıkartın ; belki (A=...)<=b-> (A=...)<b?
tsh

@ tsh Bu şimdi gerçekten güvenli. Teşekkürler!
Arnauld


1

Java 8, 208 205 bayt

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;}

Kesinlikle golf oynayabilirim. Şimdi dört üç iç içe halka için en belirgin yaklaşımı kullanıyorum .

Sıra ve sütunların iç halkalarını tek bir ilmek halinde birleştiren @ceilingcat sayesinde -3 bayt .

Açıklama:

Çevrimiçi deneyin.

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`
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.