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)でも(1,0)でも(1,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)で計算される最大面積を持つ長方形または長方形の1つを見つけることです。
  • 最大面積が同じ長方形が複数ある場合は、いずれかを出力します。必要に応じて、(上座標、左座標、右座標、下座標)辞書編集的に最小のもの。
  • 長方形のエッジは、ボードのエッジに平行でなければなりません。
  • 各文字は、AからZまでの印刷可能なASCII文字です(両方とも含まれます)。

出力

出力は、最大面積の長方形の角の左上と右下の位置でなければなりません。最初のサンプル「ボード」では、大きな正方形は黄色の正方形です。

ここに画像の説明を入力してください

答えは次のとおりです。

[1、1、8、4]

2番目のサンプルテストケース

以下の入力:

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

エリアを識別するこれらの3つの座標リストのいずれかを6つの長方形で生成する必要があります。

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

この質問は、「Stack Overflow」というタイトルで投稿されています。4つの同一の角で形成された2D配列で最大の長方形を見つける方法は?そして、この失礼なJSソリューションでは(私のコードですので「失礼」と言えます;)

さて、私の最初の投稿です、私と一緒に寛容にしてください。クイズを改善するためにあなたが言うすべてを変更します。


7
こんにちは、PPCGへようこそ!これは良い挑戦のように思えますが、勝利基準を欠いているようです。通常、ここの投稿には[code-golf]というタグが付けられます。つまり、最短のコード(バイト単位)が優先されます。
コナーオブライエン

1
質問がメインサイトに投稿される前にフィードバックを得るために使用できるサンドボックスあることをお知らせします。サンドボックスは、ここにいるほとんどすべての人にとって有用ですが、特に初心者は、私たちが持っているすべての規則と期待を知らないかもしれません。
小麦ウィザード

2
一部の回答では、例に見られるように(左、上、右、下)ではなく、「最初の」長方形(つまり、上、左、下、右)のソート順に座標を出力します。これでいい?
nimi

2
あまり厳密でない出力形式は、通常、より多くの回答を促し((left,top),(right,bottom))ます。私は答えを削除し、質問が完全に洗練されたときにもう一度答えました。
アンス

1
確かに、あなたが答えを受け入れようとするなら、それは全体で最も短いはずです、これはほとんどの人がサイトで行われたものを好む方法です。ただし、そうしないことによる影響はありません。また、回答を受け入れることはサイトにとって有害で​​あるという意見増えています。私はその意見を持っているので、私の挑戦についての答えを決して受け入れません。あなたがすることはあなた次第です。
小麦ウィザード

回答:


6

パイソン2148の 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

いいえ、あなたの答えは正しいです!いいね
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*

置換は次のとおりです。右の列、上の行、左の列、長方形の面積の否定(文字列は、幅の文字列を高さの数よりも1回多く繰り返すことの長さとして計算されます)、左の列、上の行、右の列、下の行に評価される式が続きます(キャプチャには12バイトのコストがかかり、1桁の変数が不足します)。最初の4つのキャプチャは、優先順位のソート順を表しています。Retinaは安定してソートするため、各ソート列ごとに優先度が低い順にソートすることにより、複数列ソートを確立できます。(エリアは降順でソートする必要があるため、単一の文字列ソートは使用できません。)

4{N`

次に、4つの数値ソートが実行されます。

)m`^.*?,

ソート列は、各ソート後に削除されます。

0G`

したがって、最初のエントリが望ましい結果になりました。

注:所定の領域の長方形の選択に関する制限はその後緩和され、次の144の 143バイトバージョンは、より高い長方形ではなく、より広い長方形を好みます。

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

オンラインでお試しください!


辞書式分間の要件(例えばOPに追加テストケースIを試してみてください)(多分も出力が誤った順序??にすることができます)失敗TIO
ジョナサン・アラン

(...出力の最初の2つの値は間違っていると思います)
ジョナサンアラン

いくつかの制限(辞書編集の最小要件)を緩和しました。あなたにとって問題にならないことを願っています。
-danihp

...これは、ラインとポイントを一致させる必要があります。
ジョナサンアラン

辞書順コストを固定20バイト:-(と私は別の2バイトを要しており、面積計算が変更されたことに気づいたが、私はポイントに関する手段を@JonathanAllanかわからない。
ニール・

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

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:入力を転置するだけの問題だと主張できます。
-Angs

私にとっては大丈夫です。入力を転置できます。
danihp


3

JavaScript(ES6)、121バイト

@ l4m2による
-1バイト@tshによる-1バイト
+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;}

間違いなくゴルフをすることができます。4つの 3つのネストされたforループを使用する最も明白なアプローチを使用します。

@ceilingcatが行と列の内側のループを1つのループに結合したため、-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`
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.