1

我已经使用元组的排列实现了一个魔方。没有变化的立方体表示为 (0, 1, 2, ... , 45, 46, 47)。

为了对立方体应用“转”,数字被打乱了。我已经非常全面地测试了我所有的轮次,以至于我相当确定没有错别字。

我一直在尝试实现一种检查多维数据集是否有效的方法,因为 (1, 2, ... 47, 48) 的 12 个随机排列中只有 1 个是有效的多维数据集。要使排列成为有效的魔方,它必须满足 3 个要求。这在这个 SO 线程中有很好的记录:https ://math.stackexchange.com/questions/127577/how-to-tell-if-a-rubiks-cube-is-solvable

这 3 个步骤是: 边缘方向:边缘翻转的数量必须是偶数。拐角方向:拐角扭曲的数量必须能被 3 整除。排列奇偶校验:这是我遇到麻烦的地方。排列奇偶校验必须是偶数,这意味着角奇偶校验必须匹配边缘奇偶校验。

SymPy 库为我提供了一种处理许多排列组属性的好方法,因此我将它包含在我计算排列奇偶性的尝试中。

它应该成功时失败的最简单的测试输入是立方体的后转,表示为 B。

这是代码:

def check_permutation_parity(cube):
    corners = cube[:24]
    edges = cube[24:]
    edges = [e - 24 for e in edges]

    corner_perms = corner_perms_only(corners)
    edge_perms = edge_perms_only(edges)

    normalized_corners = [int(c/3) for c in corner_perms]
    normalized_edges = [int(e/2) for e in edge_perms]

    sympy_corners = Permutation(list(normalized_corners))
    sympy_edges = Permutation(list(normalized_edges))

    corners_perm_parity = Permutation(list(normalized_corners)).parity()
    edges_perm_parity = Permutation(list(normalized_edges)).parity()

    if corners_perm_parity != edges_perm_parity:
        return False

    return True

使用一堆打印语句,我概述了整个代码中发生的情况:

这是初始状态。这是立方体的 B 排列,看起来和预期的一样。

cube:

(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 20, 12, 13, 14, 21, 22, 23, 15, 16, 17, 24, 25, 26, 27, 30, 31, 28, 29, 32, 33, 36, 37, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47)

接下来我们看看角落和边缘。请记住,每个边缘都减去了 24。这对于最终转换为 SymPy 排列是必要的。

corners, edges

(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 20, 12, 13, 14, 21, 22, 23, 15, 16, 17)

[0, 1, 2, 3, 6, 7, 4, 5, 8, 9, 12, 13, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]

然后我们只提取每 3 个角和每 2 个边。这让我们只看每个部分的排列,因为我们不关心方向。

corner_perms_only, edges_perms_only

(0, 3, 6, 9, 18, 12, 21, 15)

(0, 2, 6, 4, 8, 12, 10, 14, 16, 18, 20, 22)

然后我们按 2 或 3 占卜以转换为 SymPy

normalized_corners, edges

[0, 1, 2, 3, 6, 4, 7, 5]

[0, 1, 3, 2, 4, 6, 5, 7, 8, 9, 10, 11]

转换为 SymPy 后,角落看起来像这样:

sympy corners

(4 6 7 5)

[(4, 5), (4, 7), (4, 6)]

[[0], [1], [2], [3], [4, 6, 7, 5]]

边缘看起来像这样:

sympy edges

(11)(2 3)(5 6)

[(2, 3), (5, 6)]

[[0], [1], [2, 3], [4], [5, 6], [7], [8], [9], [10], [11]]

给我们这个奇偶校验,因为角由 3 个周期组成,边缘由 2 个周期组成:

角、边等价

1

0

因为奇偶校验不同,所以函数返回 false。

B:错误

我们知道奇偶校验应该匹配,但我无法得到这个结果,而且我有点迷失在哪里进行进一步的调试。所有代码都可以在我的 GitHub 上找到:https ://github.com/elliotmartin/RubikLite/blob/master/Rubik.py

4

1 回答 1

0

我的问题与 SymPy 和排列奇偶校验无关。为了检查这一点,我实现了自己的循环分解算法,然后检查了奇偶校验。最后,问题与我如何为每一步设置排列有关。

我想我已经学到了很多关于测试的知识——如果你的测试没有测试正确的东西,那么它们就没有那么有用了。

于 2019-02-01T01:59:15.740 回答