64 种操作,18 个方程——魔表的朴素线性模型
魔表02:64 种操作的线性方程组模型
回顾
在上一篇文章中,我们认识了魔表的基本面貌,并总结了几条关键数学性质:
- 指针状态是模 12 的离散量
- 操作效果与当前状态无关
- 操作效果可以线性叠加,且操作顺序可交换
- 逆时针转动等价于顺时针取负
这些性质共同指向了一个事实:魔表的指针变化本质上是一个模 12 上的线性系统。
本文通过建立一个数学模型,来把这个线性系统的完整面貌展现出来。
一、数学建模
1.1 状态向量
魔表正反面各有 9 个表盘,共 18 根指针。我们沿用上一篇的编号约定:
其中 \(\mathbb{Z}_{12} = \mathbb{Z} / 12\mathbb{Z}\) 是模 12 整数环。目标状态是全 12 点,即零向量 \(\mathbf{0}\)。
1.2 基本操作
一个基本操作由两个因素决定:
- 按钮状态 \(S\):4 个按钮各有按下/弹起两种状态,共 \(2^4 = 16\) 种
- 拨轮选择 \(w \in \{\mathrm{UL}, \mathrm{UR}, \mathrm{DR}, \mathrm{DL}\}\):4 种
所以一共有 \(16 \times 4 = 64\) 种"按钮-拨轮"组合。
每种组合 \((S, w)\) 对应一个固定的效果向量 \(\mathbf{e}_{S,w} \in (\mathbb{Z}_{12})^{18}\)。它的含义是:
在按钮状态 \(S\) 下,顺时针转动拨轮 \(w\) 恰好 1 格对 18 根指针造成的变化量。
1.3 多格转动与逆时针
由于性质 3(线性叠加),顺时针转动 \(k\) 格的效果就是 \(k \cdot \mathbf{e}_{S,w}\)。
由于性质 4(逆时针取负),逆时针转动 \(k\) 格等价于顺时针转动 \(12 - k\) 格,效果为 \((12 - k) \cdot \mathbf{e}_{S,w}\)。
因此,我们不需要为逆时针单独建向量。把所有操作的效果都表示成 \(\mathbf{e}_{S,w}\) 的整数倍即可。
1.4 总效果方程
设变量 \(k_{S,w} \in \mathbb{Z}_{12}\) 表示在按钮状态 \(S\) 下,顺时针转动拨轮 \(w\) 的格数。
从当前状态 \(\mathbf{x}\) 出发,所有操作的总效果 \(\mathbf{y}\) 为:
要回到全 12 点,需要总效果恰好抵消当前状态:
即:
这就是魔表求解问题的核心方程。
对于 64 种基本操作的效果向量 \(\mathbf{e}_{S,w}\) 都是已知且唯一确定的,因此我们要求的就是这 64 种基本操作对应的 64 个转动格子数 \(k_{S,w}\) 。换句话说,这就是一个有 18 个方程、64 个未知数( \(k_{S,w}\) )的模 12 线性方程组,我们只需要采用线性代数的手段,求解这个线性方程组即可得出这 64 种基本操作每个应该转动的格数。这样,也就能够找到还原这个魔表的方法了。
二、矩阵形式
把 64 个效果向量排成一个矩阵:
\(\mathbf{A}\) 是一个 \(18 \times 64\) 的矩阵,每列的 \(\mathbf{e}_{S,w}\) 都是一个18维的效果向量。这个矩阵记录的信息是 64 种基础操作中每种操作对应的 18 个表盘指针的变动量。
把所有变量 \(k_{S,w}\) 排成一个 64 维列向量:
则核心方程写成紧凑的矩阵形式:
整个问题变成了:给定状态 \(\mathbf{x}\),在模 12 下求解 \(\mathbf{k}\)。
三、如何标定 \(\mathbf{A}\)
构建矩阵 \(\mathbf{A}\) 需要我们逐一测出 \(64\) 个效果向量。方法很直接:
对每一个按钮-拨轮组合 \((S, w)\):
- 将魔表恢复到全 \(12\) 点状态
- 把按钮设置成 \(S\)
- 顺时针转动拨轮 \(w\) 恰好 \(1\) 格
- 记录 \(18\) 根指针当前指向的点数(这就等价于记录了每个指针各自变化了多少小时(顺时针记 \(+1\),逆时针记 \(-1\)))
- 这组变化量就是 \(\mathbf{e}_{S,w}\)
重复 \(64\) 次,填满矩阵 \(\mathbf{A}\) 的 \(64\) 列。
举个例子
例如我们把 只按下左上角按钮(UL),转动左上角拨轮(UL) 规定为第一种基本操作 \((S_1,w_1)\) 。那么在恢复状态下顺时针拨动一格,实际结果如下图:
可以观察到,从正面看,只有左上角按钮按下去,效果是只有左上角的指针顺时针转动 1 小时;从反面看,相当于是只有右上角的按钮抬起,效果是右上角的四个指针都逆时针转动了 1 小时。
即当前盘面情况为(把12点写作0点):
用数学的语言来表达,这个效果向量就应该写为:
这也就是矩阵 \(\mathbf{A}\) 的第一列数据了。以此类推,我们需要挨个测试总共64种基础操作,把他们对应的指针变换效果全都表示出来,形成完整的矩阵 \(\mathbf{A}\) 。
四、如何求解
得到 \(\mathbf{A}\) 后,解模 12 线性方程组 \(\mathbf{A}\mathbf{k} \equiv -\mathbf{x} \pmod{12}\),就能得到一组操作方案。
由于模 12 不是域,不能直接用高斯消元。常用的处理方式有两种:
- Smith 标准型:对 \(\mathbf{A}\) 在整数环上做 Smith 标准型分解,统一处理模 12 的约束。
- CRT 拆分:利用中国剩余定理 \(\mathbb{Z}_{12} \cong \mathbb{Z}_3 \times \mathbb{Z}_4\),分别在模 3 和模 4 下求解(此时模数是质数或质数幂),再合并。模 3 下可直接高斯消元,模 4 下稍复杂但也比直接解模 12 容易。
两种方法都是标准的线性代数技术,本文暂不展开算法的具体实现。
解出 \(\mathbf{k}\) 后,对于每个分量 \(k_{S,w}\) :
- 若 \(k_{S,w} = 0\):不执行该操作
- 若 \(1 \le k_{S,w} \le 6\):在按钮状态 \(S\) 下,顺时针转动拨轮 \(w\) 正好 \(k_{S,w}\) 格
- 若 \(7 \le k_{S,w} \le 11\):在按钮状态 \(S\) 下,逆时针转动拨轮 \(w\) 正好( \(12 - k_{S,w}\) )格
由于操作可交换,这些步骤可以按任意顺序执行。这样按照计算出来的 \(\mathbf{k}\) 转动之后,魔表就会被完全复原了。
五、一个具体状态来走一遍
为了更直观地说明这套流程,我们不妨用一个例子来走一遍。
在这个图片当中,展示了一种打乱状态下的魔表,我们首先要做的是把每个表盘指针指向的点数读出来。
我们接下来就把这 18 个数字按照我们之前定义的顺序,写成一个列向量(不要忘记把 12 改成 0 哦),这就是我们的初始状态 \(\mathbf{x}\) 。
我们的目标是找到一组操作 \(k_{S,w}\),使 \(\mathbf{A}\mathbf{k} \equiv -\mathbf{x} \pmod{12}\),即:
\(\mathbf{A}\) 是我们辛苦标定出来的一个 \(18 \times 64\) 的矩阵,带入式子中,我们利用线性代数的方法来求解 \(\mathbf{k}\) 即可。
倘若我们求解出的 \(\mathbf{k}\) 结果如下(此处随便举的例子):
那么我们复原这个魔表的操作就是:
-
对于第一个基础操作,我们要顺时针转动 2 格;
-
对于第二个基础操作,我们要逆时针转动 3 格;
-
对于第三个基础操作,我们直接跳过,无需操作;
……
- 对于第六十四个基础操作,我们要逆时针转动 4 格。
由于第一篇提到的性质3,这 64 种操作的执行顺序无关最后的结果,都能复原整个魔表。
六、反思:这个方法的问题在哪里
\(\qquad\)上述方法在数学上看起来没有任何问题。\(18\) 个方程,\(64\) 个未知数,解空间很大,总能找到一组解。
\(\qquad\)但它的工程问题在于:标定 64 个效果向量太费劲了。
\(\qquad\)你要对着魔表,逐一设置 64 种按钮组合、逐一转动拨轮、逐一记录 18 根指针的变化量。64 次手工标定,每次要记录 18 个数字,稍有不慎就会出错。
\(\qquad\)更重要的是,你只要把玩魔表几分钟就会发现——这 64 种操作根本不是互相独立的。很多操作的效果矩阵,看起来就是前几个操作的“镜像”或“旋转”。例如,在只按下 UL,转动 UL 拨轮的效果,和在只按下 UR,转动 UR 拨轮的效果,似乎只是把整个盘面旋转 90° 的结果。
\(\qquad\)这暗示了一个关键事实:我们可以利用魔表结构上的对称性,从少数几个基础操作,推导出全部 64 个效果向量。
\(\qquad\)下一篇文章,我们将探究魔表的对称性,利用对称性这一强有力的工具,将手动标定64个效果向量的过程大幅简化。

本文在前一篇的基础上,建立了魔表的完整数学模型。文章定义了状态向量和 64 种基本操作的效果向量,将魔表的求解问题转化为一个模 12 线性方程组,并讨论了如何标定一个关键的 18 × 64 的效果矩阵,简单介绍了求解模 12 线性方程组的两种思路(Smith 标准型和 CRT 拆分)。最后反思了这种方法的不足,引出利用对称性来简化工作量的策略。
浙公网安备 33010602011771号