Hình chữ nhật lớn nhất trong mảng 2d


26

Đầu vào

Bảng: Một thùng chứa 2D (ma trận, danh sách các danh sách, v.v.) của các chữ cái như:

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

Nếu bạn chọn một danh sách các danh sách, bạn có thể cho rằng tất cả các danh sách phụ có cùng độ dài.

Quy tắc

  • Để tạo một hình chữ nhật hợp lệ, bạn cần tất cả các góc hình chữ nhật có cùng 'chữ'.
  • Ví dụ, nhìn bảng mẫu với X dưới đây. Bạn có thể thấy 'X' trên (1,0) cũng trên (4,0) cũng trên (1,3) và trên (4,3) sau đó bạn có trực tràng [1,0,4,3] có nghĩa là từ (1,0) đến (4,3):

Bảng mẫu với 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"]
  • Mục tiêu là tìm hình chữ nhật hoặc một trong những hình chữ nhật có diện tích lớn nhất, được tính theo (phải-trái + 1) * (dưới cùng trên cùng + 1)
  • Nếu có nhiều hình chữ nhật có cùng diện tích tối đa, hãy xuất bất kỳ hình chữ nhật nào. Tùy chọn một với (tọa độ trên cùng, tọa độ trái, tọa độ phải, tọa độ dưới cùng) nhỏ nhất về mặt từ vựng.
  • Hình chữ nhật phải có các cạnh song song với cạnh của bảng.
  • Mỗi chữ cái là một ký tự ASCII có thể in từ A đến Z (bao gồm cả hai).

Đầu ra

Đầu ra phải là vị trí bên trái và bên phải của các góc hình chữ nhật có diện tích lớn nhất. Đối với mẫu "bảng" đầu tiên, hình vuông lớn là màu vàng:

nhập mô tả hình ảnh ở đây

Và câu trả lời nên là:

[1, 1, 8, 4]

Một trường hợp thử nghiệm ví dụ thứ hai

Một đầu vào của:

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

Nên mang lại một trong ba danh sách tọa độ xác định một khu vực sáu hình chữ nhật:

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

Câu hỏi này được đăng trên Stack Overflow với tiêu đề: Làm thế nào để tìm hình chữ nhật lớn nhất trong một mảng 2D được hình thành bởi bốn góc giống nhau? và với giải pháp JS thô lỗ này (tôi có thể nói "thô lỗ" vì là mã của tôi;):

Ok, là bài viết đầu tiên của tôi, hãy khoan dung với tôi. Tôi sẽ thay đổi tất cả những gì bạn nói để cải thiện bài kiểm tra.


7
Xin chào, chào mừng đến với PPCG! Đây có vẻ là một thử thách tốt, nhưng dường như không có bất kỳ tiêu chí chiến thắng nào. Thông thường, các bài đăng ở đây được gắn thẻ [code-golf], có nghĩa là mã ngắn nhất (tính bằng byte) sẽ thắng.
Conor O'Brien

1
Tôi nghĩ rằng tôi sẽ cho bạn biết rằng chúng tôi có một hộp cát mà bạn có thể sử dụng để nhận phản hồi về các câu hỏi trước khi chúng được đăng lên trang web chính. Sandbox hữu ích cho khá nhiều người ở đây, đặc biệt là những người mới bắt đầu, những người có thể không biết tất cả các quy tắc và kỳ vọng mà chúng tôi có.
Thuật sĩ lúa mì

2
Một số câu trả lời đưa ra tọa độ theo thứ tự sắp xếp cho hình chữ nhật "đầu tiên" (nghĩa là trên, trái, dưới, phải) thay vì (trái, trên, phải, dưới) như trong ví dụ của bạn. Được không
nimi

2
Các định dạng đầu ra ít nghiêm ngặt hơn thường khuyến khích nhiều câu trả lời hơn, do đó, một cái gì đó cũng ((left,top),(right,bottom))sẽ ổn. Tôi đã xóa câu trả lời của mình và trả lời lại khi câu hỏi được hoàn thiện.
Angs

1
Chắc chắn, nếu bạn sẽ chấp nhận một câu trả lời thì đó phải là tổng thể ngắn nhất, đây là cách mà hầu hết mọi người thích mọi thứ được thực hiện trên trang web. Tuy nhiên không có hậu quả cho việc không làm như vậy. Cũng có một ý kiến ​​ngày càng tăng rằng chấp nhận câu trả lời là bất lợi cho trang web. Tôi có ý kiến ​​đó, và do đó tôi không bao giờ chấp nhận câu trả lời về những thách thức của mình. Những gì bạn làm là tùy thuộc vào bạn.
Thuật sĩ lúa mì

Câu trả lời:


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

Hãy thử trực tuyến!


Xin chào @ovs, là dành cho bạn và bất tiện nếu tôi thay đổi quy tắc để tìm ra khu vực thành: (x2-x1 + 1) × (y2-y1 + 1) như Angs đã đề xuất?
danihp

Tôi muốn thư giãn một số quy tắc để khuyến khích câu trả lời nhiều hơn. Tôi có thể?
danihp

@danihp Hãy tiếp tục. Điều này không làm mất hiệu lực câu trả lời của tôi, phải không?
trứng

Không, câu trả lời của bạn là đúng! Tốt đẹp.
danihp

5

Võng mạc , 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`

Hãy thử trực tuyến! Chỉnh sửa: Đã lưu 1 byte vì dấu vết )khớp với $.(ẩn. Giải trình:

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

Biểu thức chính quy này phù hợp với hình chữ nhật. Các nhóm như sau: 1) Hàng trên cùng (như số lần chụp) 2) Cột bên trái (theo chiều dài) 3) Cân bằng để đảm bảo các góc bên trái thẳng hàng 4) Chữ cái cho các góc 5) Chiều rộng + 1 (theo chiều dài) 6) Cân bằng để đảm bảo các góc bên phải thẳng hàng 7) Cột bên phải (theo chiều dài) 8) không sử dụng 9) Chiều cao (như số lần chụp). Các wĐảm bảo rằng tất cả các tùy chọn độ rộng có thể có của hình chữ nhật phù hợp cho mỗi đầu cho trái góc. Các $tùy chọn liệt kê các kết quả bằng cách sử dụng mẫu thay thế sau.

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

Các thay thế như sau: Cột bên phải, hàng trên cùng, cột bên trái, phủ định diện tích của hình chữ nhật (được tính theo nghĩa đen là độ dài lặp lại chuỗi chiều rộng nhiều hơn một lần so với số lần chiều cao), cột bên trái , hàng trên cùng, cột bên phải, theo sau là một biểu thức ước tính cho hàng dưới cùng (một bản chụp sẽ có giá 12 byte cộng với tôi đã hết các biến có một chữ số). Bốn ảnh chụp đầu tiên thể hiện thứ tự sắp xếp theo thứ tự ưu tiên. Khi Retina sắp xếp ổn định, một loại nhiều màu có thể được thiết lập bằng cách sắp xếp theo từng cột sắp xếp lần lượt từ mức tối thiểu đến mức ưu tiên cao nhất. (Khu vực phải được sắp xếp theo thứ tự giảm dần, do đó không thể sử dụng một loại chuỗi đơn.)

4{N`

Bốn loại số sau đó được thực hiện.

)m`^.*?,

Cột sắp xếp sẽ bị xóa sau mỗi lần sắp xếp.

0G`

Do đó, mục đầu tiên là kết quả mong muốn.

Lưu ý: Hạn chế về việc lựa chọn hình chữ nhật của một khu vực nhất định đã được nới lỏng và phiên bản 144 143 byte sau thích một hình chữ nhật rộng hơn thay vì hình chữ nhật cao hơn:

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

Hãy thử trực tuyến!


Thất bại yêu cầu từ vựng-min (ví dụ thử trường hợp tôi đã thêm vào OP) (cũng có thể đầu ra có thể sai thứ tự ??) TIO
Jonathan Allan

(... vâng, hai giá trị đầu ra trong đầu ra là cách tôi nghĩ sai)
Jonathan Allan

Tôi chỉ nới lỏng một số hạn chế (yêu cầu từ điển-min). Tôi hy vọng không phải là một vấn đề cho bạn.
danihp

... Điều này bây giờ sẽ cần phải phù hợp với các dòng và điểm.
Jonathan Allan

Việc sửa thứ tự từ điển tốn 20 byte :-( và tôi nhận thấy rằng phép tính diện tích đã thay đổi, tốn thêm 2 byte, nhưng tôi không biết @Jonathan ALLan có ý nghĩa gì về các điểm.
Neil

4

Jelly , (27?)  29  28 byte

27 nếu lập chỉ mục dựa trên 1 được cho phép - xóa dấu vết

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

Một chương trình đầy đủ.

Hãy thử trực tuyến! (hoặc xem trường hợp thử nghiệm khác )

Làm sao?

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 byte

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

Hãy thử trực tuyến!

Trả về danh sách các danh sách ((x0 y0) (x1 y1)) .

Giải trình

{
  ([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 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]

Hãy thử trực tuyến!


Bạn có thể loại bỏ b<=d, miễn là bạn giữ a<=c.
Thuật sĩ lúa mì

@ovs thực sự cũng không hoạt động (xem ví dụ tôi đã thêm TIO )
Jonathan Allan

@nimi: Tôi có thể tranh luận rằng đó chỉ là vấn đề chuyển đổi đầu vào.
Angs

Nó ổn với tôi. Bạn có thể hoán vị đầu vào.
danihp


3

JavaScript (ES6), 121 byte

-1 byte nhờ @ l4m2
-1 byte nhờ @tsh
+2 byte để tuân thủ quy tắc chấm điểm hình chữ nhật mới

Đưa đầu vào như một ma trận của các chuỗi. Trả về tọa độ 0 được lập chỉ mục: [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

Hãy thử trực tuyến!


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

Nếu có nhiều hình chữ nhật có cùng diện tích tối đa, hãy xuất bất kỳ hình chữ nhật nào ; có lẽ (A=...)<=b-> (A=...)<b?
tsh

@tsh Điều đó thực sự an toàn. Cảm ơn!
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;}

Chắc chắn có thể chơi golf .. Bây giờ tôi sử dụng cách tiếp cận rõ ràng nhất là sử dụng bốn ba vòng lặp lồng nhau.

-3 byte nhờ @ceilingcat kết hợp các vòng lặp bên trong của hàng và cột thành một vòng lặp.

Giải trình:

Hãy thử trực tuyến.

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`
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.