Crossword 生成所有唯一的纵横字谜网格
我想生成特定网格大小的所有唯一纵横字谜网格(4x4是一个不错的大小)。所有可能的谜题,包括非唯一谜题,都由一个具有网格区域长度的二进制字符串表示(对于4x4,为16),因此所有可能的4x4谜题都由0到2^16范围内所有数字的二进制形式表示 生成这些用例很容易,但我很好奇,是否有人有一个好的解决方案,可以通过编程消除无效和重复的用例。例如,所有具有单列或单行的拼图在功能上都是相同的,因此消除了这8种情况中的7种。此外,根据纵横字谜游戏的惯例,所有的方块必须是连续的。我成功地删除了所有重复的结构,但我的解决方案需要几分钟才能执行,可能并不理想。我对如何检测连续性有些不知所措,所以如果有人对此有想法,我将不胜感激Crossword 生成所有唯一的纵横字谜网格,crossword,Crossword,我想生成特定网格大小的所有唯一纵横字谜网格(4x4是一个不错的大小)。所有可能的谜题,包括非唯一谜题,都由一个具有网格区域长度的二进制字符串表示(对于4x4,为16),因此所有可能的4x4谜题都由0到2^16范围内所有数字的二进制形式表示 生成这些用例很容易,但我很好奇,是否有人有一个好的解决方案,可以通过编程消除无效和重复的用例。例如,所有具有单列或单行的拼图在功能上都是相同的,因此消除了这8种情况中的7种。此外,根据纵横字谜游戏的惯例,所有的方块必须是连续的。我成功地删除了所有重复的结构,但
我更喜欢python的解决方案,但可以用您喜欢的语言编写。如果有人愿意,我可以发布我的python代码来生成所有网格并删除重复的网格,尽管速度可能很慢。免责声明:除所有测试外,大多数未经测试的测试都会产生影响,过滤掉一些网格,并修复一些发现的错误。当然可以优化
def is_valid_grid (n):
row_mask = ((1 << n) - 1)
top_row = row_mask << n * (n - 1)
left_column = 0
right_column = 0
for row in range (n):
left_column |= (1 << (n - 1)) << row * n
right_column |= 1 << row * n
def neighborhood (grid):
return (((grid & ~left_column) << 1)
| ((grid & ~right_column) >> 1)
| ((grid & ~top_row) << n)
| (grid >> n))
def is_contiguous (grid):
# Start with a single bit and expand with neighbors as long as
# possible. If we arrive at the starting grid then it is
# contiguous, else not.
part = (grid ^ (grid & (grid - 1)))
while True:
expanded = (part | (neighborhood (part) & grid))
if expanded != part:
part = expanded
else:
break
return part == grid
def flip_y (grid):
rows = []
for k in range (n):
rows.append (grid & row_mask)
grid >>= n
for row in rows:
grid = (grid << n) | row
return grid
def rotate (grid):
rotated = 0
for x in range (n):
for y in range (n):
if grid & (1 << (n * y + x)):
rotated |= (1 << (n * x + (n - 1 - y)))
return rotated
def transform (grid):
yield flip_y (grid)
for k in range (3):
grid = rotate (grid)
yield grid
yield flip_y (grid)
def do_is_valid_grid (grid):
# Any square in the topmost row?
if not (grid & top_row):
return False
# Any square in the leftmost column?
if not (grid & left_column):
return False
# Is contiguous?
if not is_contiguous (grid):
return False
# Of all transformations, we pick only that which gives the
# smallest number.
for transformation in transform (grid):
# A transformation can produce a grid without a square in the topmost row and/or leftmost column.
while not (transformation & top_row):
transformation <<= n
while not (transformation & left_column):
transformation <<= 1
if transformation < grid:
return False
return True
return do_is_valid_grid
def valid_grids (n):
do_is_valid_grid = is_valid_grid (n)
for grid in range (2 ** (n * n)):
if do_is_valid_grid (grid):
yield grid
for grid in valid_grids (4):
print grid
def是有效的网格(n):
row_mask=(1是允许“聚集在一起”的正方形吗?例如is 65535(使用所有正方形)一个有效的4x4网格?@douplep:这绝对是一个有效的网格。不过,我不太确定我是否理解你的意思——连续性规则意味着所有有效网格必须聚集在一起。另一个问题:单列和单行是否相同。例如,作为彼此旋转/反射的两个网格是否相同?它们将是重复的r原始帖子:>所有具有单列或单行的谜题在功能上都是相同的,因此消除了这8个谜题中的7个。这看起来很棒!我现在正在进行重构,这样我就可以打印出所有有效的、唯一的网格来进行人工检查。我还没有因果报应,但如果可以的话,我会对此进行升级。我想你可以升级即使是现在。无论如何,不幸的是,它不是很正确。连续性测试被破坏了。如果我能找到一个,我将用正确的测试进行编辑。它确实得出了一些不连续的结果,但它也过滤掉了有效的网格吗?出于我的目的,我可以手动筛选出一些无效的,但我不能添加那些arbiTralyy deleted现在看起来不错,但它似乎缺少一些有效的网格…例如,一个带有一个正方形的网格。你确定吗?在以后的修复中是否有效\u网格(4)(0x8000)
这里的计算结果为True
。选择最上面的行/最左边的列可能不是最好的选择。我想您可以将其切换为最下面的行/最右边的列,那么网格1应该有效。请注意,现在应该在三个位置进行切换:变量定义、基本网格测试和转换后测试(加上转换转换)。