Tatamibari求解器


10

背景

Tatamibari是由Nikoli设计的逻辑难题。

Tatamibari拼图游戏在带有三种不同符号的矩形网格上播放:+-。和|。求解器必须根据以下规则将网格划分为矩形或正方形区域:

  • 每个分区中必须只包含一个符号。
  • 一个+符号必须包含在一个正方形。
  • |符号必须被包含在具有比宽度更大的高度的矩形。
  • -符号必须被包含在具有比高度较大的宽度的矩形。
  • 四个片段可能永远不会共享相同的角落。(这是日本榻榻米瓷砖通常的放置方式。)

以下是一个示例难题,并提供了解决方案:

Tatamibari拼图示例 Tatamibari拼图解决方案示例

任务

解决给定的Tatamibari难题。

输入输出

输入是一个2D网格,代表给定的Tatamibari拼图。每个单元包含四个字符之一:+-|,和您所选择的字符来表示一个非线索细胞。在测试用例中,使用星号*

您可以选择任何合适的输出格式,这些输出格式可以明确表示Tatamibari拼图的任何有效解决方案。这包括但不限于:(如有疑问,请在评论中提问。)

  • 4元组的列表,其中每个元组包括矩形的顶部索引,左侧索引,宽度和高度(或任何等效表示形式)
  • 与输入形状相同的数字网格,其中每个数字代表一个矩形
  • 坐标集列表,每个坐标集包括矩形中单元格的所有坐标

如果难题有多个解决方案,则可以输出任意数量(一个或多个)的有效解决方案。输入保证至少有一个解决方案。

测试用例

Puzzle:
|-*
*+|
*-*
Solution:
122
134
554
=====
Puzzle:
+***
**|*
*+**
***-
Solution:
1122
1122
3322
3344
======
Puzzle:
|*+*+
*****
****-
***+|
+****
Solution:
12233
12233
44444
55667
55667
=======
Puzzle:
****-**
**-**|*
*|*****
****-**
*******
**+*|**
*****+*
One possible solution:
1122222
1133344
1155544
1155544
6667744
6667788
6667788
===========
Puzzle:
*-****|+**
+*-******|
****+*****
*-******||
**++|*****
+****-|***
-****-**+*
********-*
|*+*+|****
*-*--**+*+
Solution:
1111122334
5666622334
7777822994
7777A2299B
CCDEA2299B
CCFFFFGGHH
IIIIJJGGHH
KLLMMNGGOO
KLLMMNGGPP
QQRRSSSTPP

规则

适用标准规则。以字节为单位的最短代码获胜。

Answers:


5

Python 2中417个 374 366字节

输入是行列表,~无提示。以格式将单个解决方案输出到stderr (x_start, width, y_start, height)

R=range
k=input()
X,Y=len(k[0]),len(k)
W,H=R(X),R(Y)
Q=[[]]
for q in Q:C=[(x,y)for(a,b,c,d)in q for x in(a,a+b)for y in(c,c+d)];max(map(C.count,C+W))<4>0<all(sum(w>x-s>-1<y-t<h<[c for r in k[t:t+h]for c in r[s:s+w]if'~'>c]==['+|-'[cmp(h,w)]]for(s,w,t,h)in q)==1for x in W for y in H)>exit(q);Q+=[q+[(s,w+1,t,h+1)]for s in W for w in R(X-s)for t in H for h in R(Y-t)]

在线尝试!对于建议的测试用例,这太低效了。


不打高尔夫球

grid = input()
total_width = len(grid[0])
total_height = len(grid)

partitions = [[]]

for partition in partitions:
    # list the corners of all rectangles in the current partition
    corners = [(x, y)
               for (start_x, width, start_y, height) in partition
               for x in (start_x, start_x + width)
               for y in (start_y, start_y + height)]
    # if no corners appears more than three times ...
    if corners != [] and max(map(corners.count, corners)) < 4:
        # .. and all fields are covered by a single rectangle ...
        if all(
                sum(width > x - start_x > -1 < y - start_y < height
                    for (start_x, width, start_y, height) in partition) == 1
                for x in range(total_width)
                for y in range(total_height)):
            # ... and all rectangles contain a single non-~
            # symbol that matches their shape:
            if all(
                [char for row in grid[start_y: start_y + height]
                    for char in row[start_x:start_x + width] if '~' > char]
                == ['+|-'[cmp(height, width)]]
                    for (start_x, width, start_y, height) in partition):
                # output the current partition and stop the program
                exit(partition)

    # append each possible rectangle in the grid to the current partition,
    # and add each new partition to the list of partitions.
    partitions += [partition + [(start_x, width + 1, start_y, height + 1)]
                   for start_x in range(total_width)
                   for width in range(total_width - start_x)
                   for start_y in range(total_height)
                   for height in range(total_height - start_y)]

在线尝试!

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.