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"]
  • 目标是找到由(right-left + 1)*(bottom-top + 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"]

应该产生标识区域的六个坐标的这三个坐标列表之一:

[1、0、2、2]
[1、0、3、1]
[3、2、5、3]

这个问题发布在Stack Overflow上,标题为:如何在由四个相同的角形成的2D数组中找到最大的矩形?并使用此粗鲁的JS解决方案(我可以说“粗鲁”,因为这是我的代码;):

好的,这是我的第一篇文章,请对我宽容。我会更改您所说的所有内容以改善测验。


7
嗨,欢迎来到PPCG!这似乎是一个很好的挑战,但似乎缺少任何获胜标准。通常,此处的帖子被标记为[code-golf],这意味着最短的代码(以字节为单位)获胜。
科纳·奥布莱恩

1
我想告诉您,我们有一个沙箱,可用于在问题发布到主站点之前获取对问题的反馈。沙箱对于这里的几乎每个人都是有用的,特别是对于可能不了解我们拥有的所有规则和期望的初学者。
Wheat Wizard

2
一些答案按照示例中的“第一个”矩形(即,上,左,下,右)而不是(左,上,右,下)的排序顺序输出坐标。这个可以吗?
nimi

2
不太严格的输出格式通常会鼓励更多答案,因此类似的东西也((left,top),(right,bottom))应该很好。问题完全完善后,我删除了我的答案并再次回答。
昂斯

1
当然,如果您要接受答案,那应该是整体上最短的答案,这就是大多数人喜欢网站上完成的事情的方式。但是,不这样做不会带来任何后果。也有越来越多的意见,接受的答案是不利的网站。我持这种观点,因此我从不接受有关挑战的答案。您的工作取决于您。
小麦巫师

Answers:


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,您好,如果您像Angs所建议的那样更改规则以将区域计算为:(x2-x1 + 1)×(y2-y1 + 1),这对您不便?
danihp

我想放宽一些规则,以鼓励更多答案。我可以吗?
danihp

@danihp继续。这不会使我的回答无效,对吗?
ovs'Apr

不,您的答案是正确的!真好
danihp

5

视网膜163162字节

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`
.*;

在线尝试!


未能达到字典最小要求(例如,尝试我添加到OP的测试用例)(也许输出的顺序也可能错误?)TIO
Jonathan Allan

(...是的,我认为输出中的前两个值是错误的方法)
Jonathan Allan

我只是放松了一些限制(字典最小要求)。希望对您没有问题。
danihp

...这将需要匹配线和点。
乔纳森·艾伦

固定词典顺序的成本为20个字节:-((我注意到面积计算发生了变化,这又花费了2个字节,但是我不知道@JonathanAllan的意思是什么。–
Neil

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的示例)
Jonathan Allan

@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现在确实是安全的。谢谢!
Arnauld


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

绝对可以打高尔夫球。我现在使用最明显的方法,即使用四个三个嵌套的for循环。

@ceilingcat将-3个字节组合在一起,将行和列的内部循环合并为一个循环。

说明:

在线尝试。

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`
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.