Python迭代器,用于Quarto游戏板的独特安排

时间:2016-12-24 21:18:16

标签: python iteration generator combinatorics

我正在研究涉及棋盘游戏Quarto的组合学问题的程序化解决方案。在Quarto中有十六个,每个都有四个二进制属性。这意味着我们可以将每个片段表示为元组(i,j,k,l),其中每个元素为0或1。为了解决我的问题,我需要迭代每种独特的方式来安排4x4游戏板上的所有部分。我可以做类似

的事情
from itertools import permutations
for board_orientation in permutations(pieces, 16):
    do_stuff(board_orientation) #takes 1 or 2 full seconds

但这意味着16! (超过20万亿次)迭代。为了避免这种情况,我试图创建一个只产生独特板方向的发生器 - 这是在一个或多个属性的旋转,反射和反转下唯一的方向(前两个属性由二面体组D4描述)。我在Tic-Tac-Toe找到了类似的问题,但我正在努力将其扩展到这个更复杂的迭代问题。

我认为解决方案涉及通过哈希树将每个板方向映射到数值,然后查看数字在各种对称操作下如何变化,但很难将其转换为代码。

1 个答案:

答案 0 :(得分:0)

通过应用反转,板对16块板是“同构的”,通过应用旋转和镜像,对于最多8块板。那套同构板最多为16 * 8 = 128。这样至少有15个!/ 8(1.6 * 10 ^ 11)电路板配置。

使用反转,每个电路板可以“转换”为左上角为0的电路板。固定一个角覆盖所有对称性,除了在对角线上通过左上角(和右下角)进行镜像。 通过在该对称性上选择两个“相对”场(如(1,2)和(2,1)),并且在其中一个中需要较小的值(例如B [1,2]< B [ 2,1])。这意味着如果B [1,2]> B [2,1]比 执行对角镜像。以描述的方式变换的板可以用15个十六进制数字串编码(左上角字段总是0)。通过左上角调用此编码规范化。

同样地,一块板可以被其他角落标准化。一个板有4个角标准化,并且让这些标准化的呼叫板ID最小。该ID唯一地编码等距板组。

现在很好的部分:-),不需要在配置生成过程中存储生成的ID。它足以生成按字典顺序排列的一个角标准化形式的板(例如左上角), 计算其他三个标准化,如果其他三个标准化中的任何一个标准化低于生成,那么我们已经通过了该配置。这是因为配置是按字典顺序生成的。

注意:可以通过检查创建板过程中的规范化值来优化代码,而不是创建整个板并执行上层检查。比如,填充两个有序字段((1,2),(2,1))而不是用其两个有序字段填充其他角落,如果第二个角的规范化必须小于左上角的规范化(仅检查前缀)两个领域)比没有必要进一步生成。因为编码必须将有序字段作为前两位数。扩展是下一个填充第三个角落字段,执行检查,而不是第四个角落字段并执行检查。