最小の長方形カバー


23

長方形カバー

次のようなビットのマトリックスがあるとします。

1 1 0 0 0 1 1 0
1 1 1 1 0 1 1 1
0 1 1 1 0 1 1 1
1 1 0 1 1 1 1 0
1 1 0 1 1 1 0 1

このマトリックスの長方形カバーを見つけたいと思います。これは、0を含まないが、すべて1を含むマトリックスの長方形のサブセットのセットです。サブセットは互いに素である必要はありません。上記のマトリックスの長方形カバーの例を次に示します。

+----+         +----+
|1  1| 0  0  0 |1  1| 0
|    |         |    |
|  +-|-----+   |    |+-+
|1 |1| 1  1| 0 |1  1||1|
+----+     |   |    || |
   |       |   |    || |
 0 |1  1  1| 0 |1  1||1|
   +-------+   |    |+-+
+----+   +-----|-+  |
|1  1| 0 |1  1 |1| 1| 0
|    |   |     +----+
|    |   |       |   +-+
|1  1| 0 |1  1  1| 0 |1|
+----+   +-------+   +-+

このカバーの長方形の数は7です。

タスク

入力は、適切な形式で取られたビットの長方形の行列です。少なくとも1つの1が含まれていると仮定できます。出力は、マトリックスの長方形カバー内の長方形の最小数です。

最も低いバイトカウントが優先されます。標準の規則が適用されます。

テストケース

[[1]] -> 1
[[1,1]] -> 1
[[1],[1]] -> 1
[[1,0,1]] -> 2
[[1,0],[0,0]] -> 1
[[1,0],[0,1]] -> 2
[[1,0],[1,1]] -> 2
[[1,1,1],[1,0,1]] -> 3
[[0,1,0],[1,1,1],[0,1,0]] -> 2
[[1,1,1],[1,0,1],[1,1,1]] -> 4
[[1,1,0],[1,1,1],[0,1,1]] -> 2
[[1,0,1,0],[1,1,1,1],[1,0,1,0]] -> 3
[[1,1,1,0],[1,0,1,0],[1,1,1,1],[0,0,1,0]] -> 4
[[1,1,1,0],[1,0,1,0],[1,1,1,1],[0,0,1,1]] -> 5
[[1,1,1,0],[1,0,1,0],[1,1,1,1],[0,1,1,1]] -> 4
[[1,1,0,0],[1,1,1,0],[0,1,1,1],[0,0,1,1]] -> 3
[[0,1,0,0],[0,1,1,1],[1,1,1,0],[0,0,1,0]] -> 4
[[0,0,1,0,0],[0,1,1,1,0],[1,1,1,1,1],[0,1,1,1,0],[0,0,1,0,0]] -> 3

これは、カルノーマップに触発されていますか?


kマップの@ThePirateBayは、すべての長方形が2のべき乗の次元を持つ必要があります。
スパー

@スパー。ええ、知ってます。私はちょうどこの挑戦のインスピレーションだったのではないかと尋ねました。

1
貪欲なアプローチのための有用なテストケース:[[0,1,0,0],[0,1,1,1],[1,1,1,0],[0,0,1,0]]、4.
isaacg

回答:



4

ゼリー 25  24 バイト

FJ‘ṁ×⁸ẆZ€Ẇ€ẎŒPFQP$$ÐṀL€Ṃ

オンラインでお試しください!典型的なゴルフの複雑さの解決策は、より大きなテストケースでさえ気にせず、タイムアウトします(すべての可能な長方形のパワーセットが検査されます*)

どうやって?

作成可能なすべての長方形を形成します。これらの長方形のパワーセットを取得し、両方ともゼロを含まず、少なくとも1回はそれぞれを含むセットのみを保持して検査します。

「両方ともゼロを含まず、各1を少なくとも1回含むセットを維持する」部分を達成するために、コードは最初に1を1以上の異なる整数のセットに強制し、ゼロをそのままにして、「一意の値の積の最大値を見つける」。

FJ‘ṁ×⁸ẆZ€Ẇ€ẎŒPFQP$$ÐṀL€Ṃ - Link: list of lists of ones and zeros, M
F                        - flatten M into a single list
 J                       - range of length = [1,2,3,...,len(flattened(M))]
  ‘                      - increment       = [2,3,4,...,len(flattened(M))+1]
   ṁ                     - mould like M - reshapes it just like M again
     ⁸                   - chain's left argument, M
    ×                    - multiply (vectorises) - unique integers > 1 at M's 1s and 0s at M's 0s
      Ẇ                  - non-empty sublists - i.e. row selections
       Z€                - transpose €ach
         Ẇ€              - non-empty sublists of €ach - column selections of those
           Ẏ             - tighten - a flat list of all of the rectangles
            ŒP           - power-set - all possible selections of rectangles
                   ÐṀ    - filter keep those for which the following is maximal:
                  $      -   last two links as a monad:
              F          -     flatten
                 $       -     last two links as a monad:
               Q         -       de-duplicate
                P        -       product
                     L€  - length of €ach - # of rectangles used by each full-cover
                       Ṃ - minimum

*についてはNによってm個のマトリックス方法を(N、M)= 2 ^(T(N)×T(M))ので、...
の方法(3,2)= 2 ^((3 + 2 + 1) ×(2 + 1))= 2 ^ 18 = 262,144(TIOリンク)way
(3,3)= 2 ^((3 + 2 + 1)×(3 + 2 + 1))= 2 ^ 36 = 68,719,476,736
way(3,4)= 2 ^((3 + 2 + 1)×(4 + 3 + 2 + 1))= 2 ^ 60 = 1,152,921,504,606,846,976
way(5,5)= 2 ^ 225〜= 5.4e + 67(最大のテストケース)
way(8,5)= 2 ^ 540〜= 3.6e + 162(例)


FJṁ×⁸ẆZ€Ẇ€ẎŒPFQS$$ÐṀL€Ṃ-1のために働きますか?rnをテストする時間はありません。
エリックアウトゴルファー

いいえ、強制されたものだけを無視したカバー1は有効なカバーと同じ製品を持ちます(たとえば、8から5の例で半回転し、(理論上)6上部をカバーしなかったために戻ります)-セルを左にして有効と見なします。)
ジョナサンアラン

...さらに簡単-テストケース[[1,0],[0,1]]1でなくを返し2ます。
ジョナサンアラン

1

JavaScript、434バイト

コード:

for(_='),d=...-1||(,Ad<=a,u[o][n]=d,    =0,(e,r,C,m))&&()=>.map((h((A,n,on<e|o<r|n>C|o>mf=u=>(q(s=(e>C[e,C]=[C,e]r>m[r,m]=[m,r]lk=1,k&=!!A)kl|=&1,=2k&lh=f=>uA,$ABf(B,$))))(($,Bae=r=C=m=,d=to-Bt=n$&n>$e   C=nn+1~ee   C=ttn-$t=oB&o>Br    m=oo+1~rr   m=tq+=sg=[],h((ca||g.push(c)gigb,j(p=1,q+=i<j&&s(b)q)';G=/[-]/.exec(_);)with(_.split(G))_=join(shift());eval(_)

Hexdump(印刷できない文字のため):

66 6F 72 28 5F 3D 27 29 2C 13 13 64 3D 12 2E 2E 2E 11 2D 31 10 7C 7C 28 0F 2C 41 0F 64 3C 3D 0E 61 2C 0C 75 5B 6F 5D 5B 6E 5D 0B 3D 64 2C 09 3D 30 2C 08 28 65 2C 72 2C 43 2C 6D 07 29 29 13 06 26 26 28 05 29 3D 3E 04 2E 6D 61 70 28 28 03 68 28 28 41 2C 6E 2C 6F 04 02 02 6E 3C 65 7C 6F 3C 72 7C 6E 3E 43 7C 6F 3E 6D 0F 01 66 3D 75 3D 3E 28 71 08 28 73 3D 07 04 28 65 3E 43 05 5B 65 2C 43 5D 3D 5B 43 2C 65 5D 13 72 3E 6D 05 5B 72 2C 6D 5D 3D 5B 6D 2C 72 5D 13 6C 08 6B 3D 31 2C 01 6B 26 3D 21 21 41 29 13 6B 05 01 6C 7C 3D 0B 26 31 2C 0B 3D 32 06 6B 26 6C 13 68 3D 66 3D 3E 75 03 41 2C 24 04 41 03 0C 42 04 66 28 0C 42 2C 24 29 29 29 29 28 28 0C 24 2C 42 04 61 10 0F 65 3D 72 3D 43 3D 6D 3D 10 2C 64 3D 74 08 02 6F 2D 42 0F 74 3D 6E 0E 24 26 6E 3E 24 05 65 09 43 3D 6E 10 12 6E 2B 31 06 7E 65 0F 65 09 43 3D 74 12 74 08 02 6E 2D 24 0F 74 3D 6F 0E 42 26 6F 3E 42 05 72 09 6D 3D 6F 10 12 6F 2B 31 06 7E 72 0F 72 09 6D 3D 74 13 71 2B 3D 73 07 06 67 3D 5B 5D 2C 68 28 28 0C 11 63 04 61 10 7C 7C 67 2E 70 75 73 68 28 63 29 13 67 03 0C 69 04 67 03 62 2C 6A 04 28 70 3D 31 2C 71 2B 3D 69 3C 6A 26 26 73 28 11 0C 11 62 29 06 71 29 27 3B 47 3D 2F 5B 01 2D 13 5D 2F 2E 65 78 65 63 28 5F 29 3B 29 77 69 74 68 28 5F 2E 73 70 6C 69 74 28 47 29 29 5F 3D 6A 6F 69 6E 28 73 68 69 66 74 28 29 29 3B 65 76 61 6C 28 5F 29

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

それはあまりゴルフではありませんが、少なくとも非常に高速に動作します。すべてのテストケースは数ミリ秒で計算できます。

非ゴルフ

f=mat=>(
  iterate=f=>mat.map((A,x)=>A.map((a,y)=>f(a,y,x))),
  fill=(x1,y1,x2,y2)=>(
    x1>x2&&([x1,x2]=[x2,x1]),
    y1>y2&&([y1,y2]=[y2,y1]),
    isFilled=0,

    canBeFilled=1,
    iterate((A,X,Y)=>X<x1|Y<y1|X>x2|Y>y2||(
      canBeFilled&=!!A
    )),

    canBeFilled&&(
      iterate((A,X,Y)=>X<x1|Y<y1|X>x2|Y>y2||(
        isFilled|=mat[Y][X]&1,
        mat[Y][X]=2
      ))
    ),

    canBeFilled&isFilled
  ),

  rectangles=0,

  iterate((a,x,y)=>a-1||(
    x1=y1=x2=y2=-1,

    start=end=0,
    iterate((A,X,Y)=>Y-y||(
      end=X,
      A||(
        start<=x&X>x&&(x1=start,x2=X-1),
        start=X+1
      )
    )),
    ~x1||(x1=start,x2=end),

    start=end=0,
    iterate((A,X,Y)=>X-x||(
      end=Y,
      A||(
        start<=y&Y>y&&(y1=start,y2=Y-1),
        start=Y+1
      )
    )),
    ~y1||(y1=start,y2=end),

    rectangles+=fill(x1,y1,x2,y2)
  )),


  ones=[],
  iterate((a,...c)=>a-1||ones.push(c)),
  ones.map((a,i)=>ones.map((b,j)=>(
    M=1,
    rectangles+=i<j&&fill(...a,...b)
  ))),

  rectangles
)

説明

Karnaughマップを解決するためのような同様のアルゴリズムを使用します。まず、少なくとも1つの1拡張不可能な長方形の一部である可能性があるものを見つけようとします。非拡張性とは、任意の方向(上、左、右、下)に拡張すると、少なくとも1つが含まれることを意味します0(または、マトリックスの境界を超えます)。そのようなもの1が見つかったら、それを含む最大の長方形を見つけ、1その長方形内のすべてのフラグを立てます。1これらの条件を満たすフラグのないがなくなるまで繰り返します。

場合によっては(16番目のテストケースのように)1、最初のステップを適用した後に残ったがあります。次に、これらすべてを列挙し、1何らかの強化されたブルートフォース検索を適用します。この手順はほとんど適用されず、これらの場合でも、1つまたは2つの組み合わせのみを総当たりでチェックする必要があるため、より大きなテストケースでも非常に高速に動作するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.