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 벨로우가 있는 샘플 보드를 보십시오 . (1,0), (4,0), (1,3) 및 (4,3)에서 'X'를 볼 수 있습니다. 그러면 [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)에 의해 계산 된 사각형 또는 가장 큰 영역을 가진 사각형 중 하나를 찾는 것입니다
  • 최대 면적이 동일한 직사각형이 여러 개인 경우 하나를 출력하십시오. 선택적으로 (상위 좌표, 왼쪽 좌표, 오른쪽 좌표, 아래쪽 좌표) 사 전형적으로 가장 작은 것.
  • 사각형의 가장자리는 보드의 가장자리와 평행해야합니다.
  • 각 문자는 A에서 Z까지 인쇄 가능한 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"]

6 개의 사각형 영역을 식별하는 다음 세 좌표 목록 중 하나를 생성해야합니다.

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

이 질문은 제목과 함께 스택 오버플로에 게시 됩니다. 네 개의 동일한 모서리로 구성된 2D 배열에서 가장 큰 사각형을 찾는 방법은 무엇입니까? 그리고이 무례한 JS 솔루션으로 (내 코드이기 때문에 "무례"라고 말할 수 있습니다.) :

좋아, 내 첫 번째 게시물입니다, 나와 관용하십시오. 퀴즈를 개선하기 위해 당신이 말하는 모든 것을 바꿀 것입니다.


7
안녕하세요, PPCG에 오신 것을 환영합니다! 이것은 좋은 도전으로 보이지만 승리 기준이 부족한 것 같습니다. 일반적으로 여기의 게시물에는 [code-golf]로 태그가 지정되어 가장 짧은 코드 (바이트)가 이깁니다.
코너 오브라이언

1
질문을 주 사이트에 게시하기 전에 질문에 대한 피드백을받는 데 사용할 수 있는 샌드 박스가 있음을 알려드립니다 . 샌드 박스는 여기에있는 거의 모든 사람에게, 특히 우리가 가진 모든 규칙과 기대치를 알지 못하는 초보자에게 유용합니다.
밀 마법사

2
일부 답변은 예에서 볼 수 있듯이 (왼쪽, 위쪽, 오른쪽, 아래쪽) 대신 "첫 번째"사각형 (즉, 위쪽, 왼쪽, 아래쪽, 오른쪽)에 대한 정렬 순서로 좌표를 출력합니다. 이거 괜찮아?
nimi

2
덜 엄격한 출력 형식은 일반적으로 더 많은 답변을 장려하므로 이와 비슷한 것도 ((left,top),(right,bottom))좋습니다. 질문이 완전히 수정되면 답변을 삭제하고 다시 답변합니다.

1
물론, 당신이 대답을 받아들이려고한다면 전체적으로 가장 짧아야합니다. 이것이 대부분의 사람들이 사이트에서하는 일을 좋아하는 방식입니다. 그러나 그렇게하지 않으면 아무런 결과가 없습니다. 답변을 받아들이는 것이 사이트에 해롭다는 의견커지고 있습니다. 나는 그런 견해를 가지고 있으므로 도전에 대한 답변을 결코 받아들이지 않습니다. 당신이하는 일은 당신에게 달려 있습니다.
위트 마법사

답변:


6

파이썬 2 , 148130 바이트

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, Angs가 제안한대로 (x2-x1 + 1) × (y2-y1 + 1)로 영역을 계산하도록 규칙을 변경하면 불편하고 불편합니까?
danihp

더 많은 답변을 장려하기 위해 몇 가지 규칙을 완화하고 싶습니다. 할 수 있습니까?
danihp

@danihp 계속하십시오. 이것은 내 대답을 무효화하지 않습니다.
ovs

응, 네 대답이 맞아! 좋은.
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 개의 캡처는 우선 순위에 따라 정렬 순서를 나타냅니다. Retina가 안정적으로 정렬됨에 따라 각 정렬 열을 순서대로 정렬하여 다중 열 정렬을 설정할 수 있습니다. 이 영역은 내림차순으로 정렬해야하므로 단일 문자열 정렬을 사용할 수 없습니다.

4{N`

그런 다음 네 가지 숫자 정렬이 수행됩니다.

)m`^.*?,

그런 다음 각 정렬 후에 정렬 열이 삭제됩니다.

0G`

따라서 첫 번째 항목은 이제 원하는 결과입니다.

참고 : 주어진 영역의 사각형 선택에 대한 제한이 완화되었으며 다음 144143 바이트 버전은 더 큰 사각형보다 넓은 것을 선호합니다.

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

온라인으로 사용해보십시오!


사전 최소 요구 사항을 충족하지 못합니다 (예를 들어 OP에 추가 한 테스트 사례를 시도하십시오) (출력이 잘못된 순서 일 수도 있습니다 ??). TIO
Jonathan Allan

(... 예, 출력에서 ​​처음 두 값은 잘못된 생각입니다.)
Jonathan Allan

방금 몇 가지 제한 사항을 완화했습니다 (사전 최소 요구 사항). 나는 당신에게 문제가되지 않기를 바랍니다.
danihp

... 이제 선과 점이 일치해야합니다.
Jonathan Allan

사전 순서가 20 바이트 인 고정 비용 :-( 그리고 나는 면적 계산이 바뀌고 또 다른 2 바이트가 필요하다는 것을 알았지 만 @JonathanAllan이 포인트에 대해 무엇을 의미하는지 모르겠다.
Neil

4

젤리 , (27?)  29  28 바이트

1 기반 색인 작성이 허용되는 경우 27-후행 제거

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

펄 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

하스켈 , 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를 추가 한 예 참조 )
Jonathan Allan

@ nimi : 나는 그것이 입력을 바꾸는 것의 문제라고 주장 할 수 있습니다.

나는 괜찮아. 입력을 바꿉니다.
danihp


3

자바 스크립트 (ES6), 121 바이트

@ l4m2 덕분에
-1 바이트 새로운 사각형 점수 규칙을 준수하기 위해 @tsh +2 바이트 덕분에 -1 바이트

입력을 문자열 매트릭스로 취합니다. 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 이제 안전합니다. 감사!
Arnauld


1

자바 8, 208205 바이트

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

확실히 골프를 칠 수 있습니다. 이제는 가장 확실한 방법을 사용합니다. 개의 개의 중첩 for 루프를 합니다.

덕분에 -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`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.