これらのセルをグループ化します!


12

この課題は、ゲームLayerzに基づいています。

標準入力または関数の引数として、各セルに空白(ペナルティなしで空白の代わりに0を使用することを選択できます)、1、2、3、または4のいずれかを含むセルの2D長方形配列; 各非空白セルがちょうど1つの領域に含まれるように、それを有効な領域(以下に定義)に分割する方法を見つけます。次に、見つかったソリューションを適切な形式で出力します。解決策がない場合は、出力を生成せずに停止するか、単一のfalsey値を出力して停止します。

次のいずれかが有効なリージョンを構成します。

  • 1を含む単一のセル
  • 2を含むセルと、その非空白の直交ネイバーの1つを含む
  • 3つおよび正確に2つの非空白の直交近傍を含むセル
  • 4のセルと、厳密に3つの非空白の直交ネイバーを含むセル

これはであるため、バイト単位での最短の有効な回答が優先されます。

いくつかのテストケース:

1.かなり些細なもの:

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

これが解決策であり、各領域は異なる色になっています。

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

2.より興味深いもの

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

これには複数のソリューションがありますが、そのうちの1つを次に示します。

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

3.解決策を持たない、空白を含む小さなもの(2つのうちの1つを使用して3つを「キャプチャ」するか、3つを使用して2つのうち2つを取得するかによって、隣接しない(したがってグループ化できない)2つのペアまたは単独の2つのペア):

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

このグリッドには解決策がないため、このグリッドが与えられたときに出力を生成せずにプログラムを停止する必要があります。

4.これは(上の2つのセルを1つ左にシフトした)解決策があります:

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

解決:

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

(右下2は3を「キャプチャ」するために使用されます)

5.いくつかの4つのテストケースが必要だったため:

1つのソリューション:


2
ASCIIバージョンのテストケースがあれば役立つので、すべてを入力する必要はありません。また、テストケースは4、それらが有効な入力である場合にも対応する必要があります。
マーティンエンダー

1
直交する隣人は、左右だけ、または対角線だけを意味しますか 上下左右だけの場合、3は他の2つの3と同じ領域にあるのはなぜですか?それらの1つは、直交ネイバーではありません。
エヤルレフ

@EyalLev左右上下のみ。右上の3とその2つの隣人が領域を構成します。
SuperJedi224

@ SuperJedi224右上の3およびその2つの隣人は有効な領域を構成します、はい、しかしそれらの隣人はそうではありません。リージョンは「クローズドセット」である必要はありませんか?すなわち、地域のすべてのメンバーはその地域の有効なメンバーでなければなりませんか?
エアルレフ

回答:


3

この課題は1年以上前のものですが、「未回答」でこれを見つけただけで、非常に興味深く見えました。

「ルート」セルの番号が各地域で唯一の重要な番号であると仮定すると(例から推測できます)、ここに私のバックトラッキングソリューションがあります。

Pythonの3355の 351 349バイト

from itertools import*
def f(a):
 D=len(a[0])+1;S={D*r+c for r in range(len(a))for c in range(D-1)if a[r][c]};s=[{x,*t}for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
 def B(s,S,d=1):
  if{0}>S:return a
  if[]==s:return 0
  h,*t=s
  if h<=S:
   for x in h:a[x//D][x%D]=d
  return h<=S and B(t,S-h,d+1)or B(t,S,d)
 return B(s,S)

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

入力形式は整数の2Dリストで、空白はゼロであり、出力形式も数値ごとに1つの領域を表す整数の2Dリストです。リージョン番号は1から始まります。ゼロは空白セル用に予約されています(入力の場合)。指定された入力が解決できない場合、関数は単一のゼロ(偽の値)を返します。

たとえば、テストケース5は次のように入力されます。

[[2,3,2],
 [3,4,3],
 [0,4,0],
 [3,3,3],
 [2,3,2],
 [0,3,0]]

そして出力は

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

Ungolfed、コメント付き:

from itertools import*
def f(a):
 # Rows, cols, fake-cols to prevent neighbors wrap around
 R,C=len(a),len(a[0]);D=C+1
 # All valid cells represented as integers
 S={D*r+c for r in range(R) for c in range(C) if a[r][c]}
 # All valid regions rooted at each cell
 s=[{x,*t} for x in S for t in combinations({x-D,x-1,x+1,x+D}&S,a[x//D][x%D]-1)]
 # Start backtracking
 return backtrack(a,s,S,D)

# a: array to fill in the region numbers
# s: current candidates of regions
# S: current remaining cells to cover
# D: constant from f
# d: recursion depth == group number in the result
def backtrack(a,s,S,D,d=1):
 # Empty S: the board is correctly covered, return the result
 if not S:return a
 # Empty s: no more candidate regions to use, return false
 if not s:return 0
 h,*t=s
 # h is not a subset of S: h is not a valid cover, try with the rest using same depth
 if not h<=S:return backtrack(a,t,S,D,d)
 # h is a valid cover, write d to the cells in h
 for x in h:a[x//D][x%D]=d
 return backtrack(a,t,S-h,D,d+1)or backtrack(a,t,S,D,d)
 

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

注:これは、NP完全であることがよく知られているセットパッキングの特殊なケースです。この特定の問題はセットサイズ(最大4)を制限し、多項式時間で「適切な」セットパッキングを見つける近似アルゴリズムが存在しますが、可能な限り最大のセットパッキングを保証しません(この問題では厳密に必要です)。

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