分组这些单元格!


12

该挑战基于游戏Layerz。

给定,在stdin上或作为函数参数,单元格的2D矩形数组,其中每个单元格包含一个空格(可以选择使用0代替空格,而不会受到任何惩罚),1、2、3或4 ; 找到一种方法将其划分为有效区域(如下所述),以使每个非空白单元格仅包含一个区域。然后,以任何合理的格式输出找到的解决方案。如果没有解决方案,则要么停止而不产生输出,要么输出一个假值,然后停止。

以下任何内容均构成有效区域:

  • 包含1的单个单元格
  • 包含2个且恰好是其非空白正交邻居之一的像元
  • 包含3个和正好两个非空白正交邻居的像元
  • 包含4个且恰好是其三个非空白正交邻居的像元

这是,因此以字节为单位的最短有效答案为准。

一些测试用例:

1.一个相当琐碎的:

在此处输入图片说明

这是解决方案,每个区域使用不同的颜色:

在此处输入图片说明

2.一个更有趣的

在此处输入图片说明

这是一个以上的解决方案,但这是其中之一:

在此处输入图片说明

3.较小的一个,包含空格,没有任何解决方案(取决于您是使用二进制之一来“捕获”这三个,还是使用三个来获取两者中的两个,要么留下一个一对不相邻的(因此不可分组的)对或单独一个对):

在此处输入图片说明

由于此网格没有解决方案,因此在指定该网格的情况下,您的程序应暂停而不产生任何输出。

4.这个(顶部2个向左移动一个单元格)确实有一个解决方案:

在此处输入图片说明

解:

在此处输入图片说明

(右下角的2用于“捕获” 3)

5.因为我们需要一个包含四个方面的测试用例:

一种解决方案:


2
如果存在测试用例的ASCII版本,这样人们就不必全部输入,这将很有帮助,4如果这些用例是有效的输入,则测试用例也应覆盖s。
Martin Ender

1
正交邻居意味着仅左上右下还是对角线?如果仅从左到右上下移动,那么3与其他两个3为何在同一区域?其中之一不是正交邻居。
Eyal Lev's

@EyalLev仅左-右-上-下。右上方的3和它的2个邻居构成了该区域。
SuperJedi224 '16

@ SuperJedi224右上方的3和它的两个邻居构成一个有效区域,是的,但是那些邻居却没有。区域不是必须是“封闭集”吗?即该区域中的每个成员都必须是该区域的有效成员?
Eyal Lev

Answers:


3

我知道这个挑战已有一年多了,但是我只是在“未回答”中发现了这个挑战,对我来说看起来很有趣。

假设“根”单元格的数量是每个区域中唯一的有效数字(可从示例中推导),这是我的回溯解决方案:

Python 3中355个 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整数列表,空白为零,输出格式也是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]]

取消评论,并附上评论:

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)
 

在线尝试!

注意:这是Set Packing的一种特殊情况,众所周知它是NP完整的。此特定问题的集合大小有限(最多4个),并且存在一种近似算法,可以在多项式时间内找到“良好的”集合装箱,但是它们不能保证最大可能的集合装箱(此问题对此是严格要求的)。

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.