python - 查找多米诺骨牌顺序的有效方法
问题描述
我有一个以这种方式工作的小型多米诺骨牌游戏:给了我一个N*N
4 块,我需要对它们进行排序,以便每两个相邻的块具有相同的编号。瓷砖可以旋转。例如,这是我的 2*2 板:
a,b,c,d = [1,2,3,4], [7,9,6,2], [6,8,8,5], [3,5,0,0]
它们可以通过以下方式可视化:
print(print_2_tiles(a,b,'a','b'))
print(print_2_tiles(d,c,'d','c'))
##############
#**1**##**7**#
#4*A*2##2*B*9#
#**3**##**6**#
##############
##############
#**3**##**6**#
#0*D*5##5*C*8#
#**0**##**8**#
##############
可以看出,“赢得”这个棋盘的唯一方法是我订购瓷砖的方式,因为<a,b>
仅通过 2 连接,<a,d>
仅通过 3 连接,依此类推……<a,c>,<b,d>
根本没有连接。任何瓷砖的旋转或移动都不会获得“胜利”。
我写了函数:
- 查找任何给定的 2 个图块之间的连接
- 计算出连接给定的 2 个图块需要多少次旋转
- 检查所有可能性并找到正确的顺序
然而,这只是一个带有 16*12*8 选项的简单案例,我可以排除许多选项,因为有独特的连接器(即连接的“2”<a,c>
在其他瓷砖中不存在)。如果我得到一个更大的板(更大的字母表也可能使事情复杂化......),比如说,5 * 5,选项的数量将是 100 * 96 * 92......并且蛮力不会削减它。
我怎样才能有效地找到正确的顺序(保证板子有一个正确的顺序)?
这是我的努力:
import numpy as np
from itertools import combinations, product
# returns list of [<connector element>, <indices of element in a>, <indices of element in b>]
def find_connections(a,b):
intersected_elem = np.array(list(set(a).intersection(b)))
possible_connections = []
for val in intersected_elem:
x = list(np.where(np.array(a) == val)[0])
y = list(np.where(np.array(b) == val)[0])
possible_connections.append([val,x,y])
return possible_connections
def str_tile(t, name):
template = '''#######
#**{}**#
#{}*{}*{}#
#**{}**#
#######'''
up,right,down,left = t
return template.format(up,left,name.upper(),right,down)
def print_2_tiles(a,b, name_a, name_b):
res = ''
for line in zip(str_tile(a,name_a).splitlines(), str_tile(b,name_b).splitlines()):
res += ''.join(line)
res += '\n'
return res[:-1]
def find_final_connections(tiles_ls):
tiles_combinations = list(combinations(tiles_ls, 2))
a_idx,b_idx = 0,1
final_connections = []
for comb in tiles_combinations:
connections = find_connections(comb[0], comb[1])
print('({},{})'.format(a_idx,b_idx), connections, end='\t')
if len(connections):
print('this meants {},{} are connected via {} in directions {},{}'.format(a_idx,b_idx, connections[0][0], connections[0][1][0], connections[0][2][0]))
final_connections.append((a_idx,b_idx))
else:
print()
# is there a neater way, using enumerate on itertools.combinations?
b_idx += 1
if b_idx == len(tiles_ls):
a_idx += 1
b_idx = a_idx + 1
print(final_connections)
a,b,c,d = [1,2,3,4], [7,9,6,2], [6,8,8,5], [3,5,0,0]
tiles_ls = [a,b,c,d]
find_final_connections(tiles_ls) # returns a 4-elem list -> success
print('#'*30)
a,b,c,d = [1,2,3,4], [7,9,6,2], [6,8,8,5], [0,5,0,0]
tiles_ls = [a,b,c,d]
find_final_connections(tiles_ls) # returns a 3-elem list -> fail
解决方案
就这么确定暴力破解不行吗?
我会尝试一个系统的解决方案,你依次选择每一个多米诺骨牌并将其放在左上角,尝试所有四个旋转。然后选择另一个多米诺骨牌并将其放在第二个位置,尝试所有四个旋转并检查是否与第一个匹配。
依此类推,在任何阶段,您从剩余的多米诺骨牌中挑选一个,尝试四次旋转并检查与已知邻居的兼容性。
这最好写成递归过程。
推荐阅读
- testng - 如果我的测试用例失败(使用 TestNG),如何运行特定方法?
- r - 我的数据绑定代码适用于 Windows,但不适用于 Mac
- osgi - OSGI 中的服务激活导致超时
- ios - 带有非登录钥匙串的 CodeSign
- docker - Docker windows 10 无法 ping LAN ip
- javascript - 在不关闭 iframe 的情况下,在后台更改父窗口的 URL 路径
- c++ - C++ 和 OpenSSL 库:如何从代码中设置 subjectAltName (SAN)?
- jmeter - 如何在使用 Jmeter 进行性能测试期间在测试运行之间获取结果 csv 文件?
- arrays - Laravel 输入对象数组到 api 路由
- python - Django:如何向模型类添加“设置和保存”方法?