【问题标题】:Python iterator for unique arrangements of Quarto game board用于Quarto游戏板独特排列的Python迭代器
【发布时间】:2016-12-24 21:18:15
【问题描述】:

我正在为一个涉及棋盘游戏 Quarto 的组合问题提供程序解决方案。在 Quarto 中有 16 个片段,每个片段具有四个二进制属性。这意味着我们可以将每个部分表示为一个元组 (i, j, k, l),其中每个元素都是零或一。为了解决我的问题,我需要迭代每一种独特的方式来将 所有 棋子排列在 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 找到了一个类似的问题,但我正在努力解决如何将其扩展到这个更复杂的迭代问题。

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

【问题讨论】:

    标签: python iteration generator combinatorics


    【解决方案1】:

    一个板通过应用反转与 16 个板“同构”,并通过应用旋转和镜像最多与 8 个板“同构”。即同构板的集合最多为16 * 8 = 128。这样至少有 15!/8 (1.6 * 10^11) 板配置。

    使用反转可以将每个板“转换”为左上角为 0 的板。固定一个角涵盖了所有对称性,除了通过左上角(和右下角)在对角线上镜像。 可以通过在该对称性上选择两个“相反”字段(如 (1,2) 和 (2,1))来覆盖该对称性,并在其中一个字段中要求较小的值(例如 B[1,2] B[2,1] 比 执行对角镜像。以所述方式转换的板可以用15位十六进制数字字符串编码(左上字段始终为0。)将这种编码标准化称为左上角。

    以同样的方式,一个板可以被其他角标准化。一个板有 4 个角归一化,并让这些归一化中的最小调用板 ID。该 ID 对一组等距板进行唯一编码。

    现在是不错的部分 :-),不需要在配置生成过程中存储生成的 ID。以一个角规范化形式(例如左上角)的字典顺序生成板就足够了, 计算其他三个归一化,如果其他三个归一化中的任何一个低于生成的比我们已经通过该配置。这是因为配置是按字典顺序生成的。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多