Найбільший прямокутник у 2d масиві


26

Вхідні дані

Дошка: 2D контейнер (матриця, список списків тощо) літер типу:

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

Якщо ви вибираєте список списків, ви можете припустити, що всі підлісти однакової довжини.

Правила

  • Щоб зробити дійсний прямокутник, вам потрібні всі кути прямокутника з однаковою літерою.
  • Наприклад, подивіться таблицю зразка з X нижче. Ви можете бачити "X" на (1,0) також на (4,0) також на (1,3) і на (4,3), тоді у вас є перерахунок [1,0,4,3], що означає від (1,0) до (4,3):

Дошка для зразка з 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"]
  • Мета - знайти прямокутник або один з прямокутників з найбільшою площею, обчислений (праворуч-ліворуч + 1) * (знизу вгорі + 1)
  • Якщо є кілька прямокутників з однаковою максимальною площею, виведіть будь-який. За бажанням той, який (верхня координата, ліва координата, права координата, нижня координата) лексикографічно найменший.
  • Прямокутники повинні мати краї, паралельні краю дошки.
  • Кожна літера - це друкована таблиця ASCII від А до Я (обидва входять в комплект).

Вихідні дані

Вихід повинен бути ліворуч і праворуч вниз, кути найбільшого за площею прямокутника. Для першого зразка «дошки» великий квадрат - жовтий:

введіть тут опис зображення

І відповідь повинна бути:

[1, 1, 8, 4]

Другий приклад тестового випадку

Вхід:

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

Потрібно отримати один із цих трьох координатних списків, що ідентифікують область із шістьма прямокутниками:

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

Це запитання розміщено у "Переповнення стека" із заголовком: Як знайти найбільший прямокутник у двовимірному масиві, утвореному чотирма однаковими кутами? і з цим грубим рішенням JS (я можу сказати "грубим", тому що це мій код;):

Гаразд, це моя перша посада, будьте толерантні зі мною, будь ласка. Я зміню все, що ви кажете, щоб покращити вікторину.


7
Привіт, Ласкаво просимо до PPCG! Це здається хорошим викликом, але, здається, не вистачає жодного критерію виграшу. Зазвичай публікації тут позначені тегами [code-golf], що означає, що найкоротший код (у байтах) виграє.
Conor O'Brien

1
Я подумав, що повідомляю, що у нас є пісочниця, яку ви можете використовувати для отримання зворотнього зв’язку з питаннями, перш ніж вони будуть розміщені на головному сайті. Пісочниця корисна майже всім тут, але особливо початківцям, які, можливо, не знають усіх правил і очікувань, які ми маємо.
Пшеничний майстер

2
Деякі відповіді виводять координати в порядку сортування прямокутника «перший» (тобто верхній, лівий, нижній, правий) замість (лівий, верхній, правий, нижній), як видно з ваших прикладів. Чи це добре?
німі

2
Менш строгі формати випуску зазвичай заохочують більше відповідей, тому щось подібне теж ((left,top),(right,bottom))має бути добре. Я видалив свою відповідь і знову відповів, коли питання повністю уточнено.
Ангс

1
Звичайно, якщо ви збираєтесь прийняти відповідь, це повинно бути найкоротшим в цілому, саме так більшість людей люблять справи, зроблені на сайті. Однак наслідків для цього немає. Також зростає думка, що прийняття відповідей шкодить сайту. Я такої думки, і тому я ніколи не приймаю відповіді на свої виклики. Що ви робите, залежить від вас.
Пшеничний майстер

Відповіді:


6

Python 2 , 148 130 байт

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

Спробуйте в Інтернеті!


Привіт @ovs, для вас і незручно, якщо я зміню правило, щоб визначити область на: (x2-x1 + 1) × (y2-y1 + 1), як це запропонував Angs?
danihp

Я хотів би розслабити деякі правила, щоб заохотити більше відповідей. Можна я?
danihp

@danihp Вперед. Це не скасовує мою відповідь, правда?
ов

Ні, ваша відповідь правильна! Приємно.
danihp

5

Сітківка , 163 162 байт

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

0G`

Спробуйте в Інтернеті! Редагувати: збережено 1 байт, тому що трейлінг, що )відповідає $.(знаку, неявний. Пояснення:

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

Цей регулярний вираз відповідає прямокутникам. Групи такі: 1) верхній рядок (як кількість захоплення) 2) лівий стовпчик (як довжина) 3) балансування для забезпечення вирівнювання лівих кутів 4) лист по кутах 5) ширина + 1 (як довжина) 6) балансування щоб забезпечити вирівнювання правих кутів 7) Правий стовпчик (як довжина) 8) невикористаний 9) Висота (як кількість захоплення). Цей wпараметр гарантує, що всі можливі ширини прямокутників відповідають кожному лівому верхньому кутку. В $опції наведені результати , використовуючи наступну схему заміщення.

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

Заміни наступні: правий стовпчик, верхній рядок, лівий стовпчик, заперечення площі прямокутника (буквально обчислюється як довжина повторення рядка ширини на один більше, ніж кількість висот), лівий стовпець , верхній рядок, правий стовпець, а потім вираз, що оцінює нижній рядок (захоплення коштувало б 12 байт плюс у мене не вистачало одноцифрових змінних). Перші чотири захоплення представляють порядок сортування за черговістю. Оскільки сітківка стабільно сортується, багатокольорову сортування можна встановити шляхом сортування за кожним стовпцем сортування по черзі від найменшого до найбільшого пріоритету. (Область повинна бути сортована у порядку зменшення, тому не можна використовувати один сортування рядків.)

4{N`

Потім виконуються чотири числові сортування.

)m`^.*?,

Потім стовпець сортування видаляється після кожного сортування.

0G`

Отже, перший запис - це бажаний результат.

Примітка: обмеження на вибір прямокутника даної області з тих пір було знято, і наступна 144 143-байтна версія надає перевагу більш широкому, а не більшому прямокутнику:

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

Спробуйте в Інтернеті!


Не виконує вимогу до лексикографічної хвилини (спробуйте тестовий випадок, який я додав, наприклад, до ОП) (можливо, також вихід може бути в неправильному порядку ??) TIO
Джонатан Аллан

(... так, перші два значення у виході є неправильним, я думаю)
Джонатан Аллан

Я просто зняв деякі обмеження (вимога лексикографічної хвилини). Я сподіваюся, це не буде проблемою для вас.
danihp

... тепер це потрібно буде відповідати лініям і точкам.
Джонатан Аллан

Виправлення лексикографічного порядку коштувало 20 байт :-( і я помітив, що змінився обчислення площі, що коштувало ще 2 байти, але я не знаю, що означає "ДжонатанАллан" про бали.
Ніл

4

Желе , (27?)  29  28 байт

27, якщо дозволено індексацію на основі 1 - видаліть трейлінг

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

Повна програма.

Спробуйте в Інтернеті! (або дивіться інший тестовий випадок )

Як?

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 байт

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

Спробуйте в Інтернеті!

Повертає список списків ((x0 y0) (x1 y1)).

Пояснення

{
  ([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 байти

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]

Спробуйте в Інтернеті!


Ви можете видалити b<=d, доки ви тримаєте a<=c.
Пшеничний майстер

@ovs насправді, що теж не буде працювати (див. приклад, який я додав TIO )
Джонатан Аллан

@nimi: Я можу стверджувати, що це лише питання перенесення інформації.
Ангс

Для мене це нормально. Ви можете перемістити вхід.
danihp


3

JavaScript (ES6), 121 байт

-1 байт завдяки @ l4m2
-1 байт завдяки @tsh
+2 байтам, щоб відповідати новому правилу балів прямокутника

Приймає введення як матрицю рядків. Повертає 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

Спробуйте в Інтернеті!


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

Якщо є кілька прямокутників з однаковою максимальною площею, виведіть будь-який ; можливо (A=...)<=b-> (A=...)<b?
tsh

@tsh Це справді безпечно. Спасибі!
Арнольд


1

Java 8, 208 205 байт

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

Однозначно можна пограти в гольф. Зараз я використовую найбільш очевидний підхід використання чотирьох трьох вкладених циклів.

-3 байти завдяки @ceilingcat поєднує внутрішні петлі рядків і стовпців в одну петлю.

Пояснення:

Спробуйте в Інтернеті.

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`
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.