魔表04:对称模型------从 6 个原型到 64 列矩阵
回顾
在上一篇文章中,我们探究了魔表的三种对称性:旋转 \(R\)、正反互补 \(C\) 和对角镜像 \(D\)。结论是:只需要手动标定 6 个原型操作,其余 58 个效果向量全部可以用对称性推导出来。
本文就来完成这件事------从 6 个 18 维向量出发,利用 \(R\)、\(C\)、\(D\),生成完整的 \(18 \times 64\) 矩阵 \(\mathbf{A}\)。
一、列的排列约定
在开始之前,需要先约定好矩阵 \(\mathbf{A}\) 的 64 列分别对应哪 64 种操作,这样后续的求解和分析才有统一的参照。
我们采用先按按钮集分组、组内按拨轮顺序的排列方式:
| 列号 | 对应操作 | 说明 |
|---|---|---|
| \(1 \sim 4\) | 按钮集 \(S_1\),拨轮 UL / UR / DR / DL | 第 1 组 |
| \(5 \sim 8\) | 按钮集 \(S_2\),拨轮 UL / UR / DR / DL | 第 2 组 |
| \(\cdots\) | \(\cdots\) | \(\cdots\) |
| \(61 \sim 64\) | 按钮集 \(S_{16}\),拨轮 UL / UR / DR / DL | 第 16 组 |
按钮集的 16 种排列顺序来自第三篇 4.2 节的表,按原型与其补集交替排列:
| 组 \(i\) | 按钮集 \(S_i\) | 生成方式 |
|---|---|---|
| 1 | \(\varnothing\) | \(v_0\) |
| 2 | \(\{\mathrm{UL},\mathrm{UR},\mathrm{DL},\mathrm{DR}\}\) | \(C(v_0)\) |
| 3 | \(\{\mathrm{UL}\}\) | \(v_1\) |
| 4 | \(\{\mathrm{UR},\mathrm{DL},\mathrm{DR}\}\) | \(C(v_1)\) |
| 5 | \(\{\mathrm{UR}\}\) | \(v_2\) |
| 6 | \(\{\mathrm{UL},\mathrm{DL},\mathrm{DR}\}\) | \(C(v_2)\) |
| 7 | \(\{\mathrm{DL}\}\) | \(D(v_2)\) |
| 8 | \(\{\mathrm{UL},\mathrm{UR},\mathrm{DR}\}\) | \(C(D(v_2))\) |
| 9 | \(\{\mathrm{DR}\}\) | \(v_3\) |
| 10 | \(\{\mathrm{UL},\mathrm{UR},\mathrm{DL}\}\) | \(C(v_3)\) |
| 11 | \(\{\mathrm{UL},\mathrm{UR}\}\) | \(v_4\) |
| 12 | \(\{\mathrm{DL},\mathrm{DR}\}\) | \(C(v_4)\) |
| 13 | \(\{\mathrm{UL},\mathrm{DL}\}\) | \(D(v_4)\) |
| 14 | \(\{\mathrm{UR},\mathrm{DR}\}\) | \(C(D(v_4))\) |
| 15 | \(\{\mathrm{UL},\mathrm{DR}\}\) | \(v_5\) |
| 16 | \(\{\mathrm{UR},\mathrm{DL}\}\) | \(C(v_5)\) |
每组内拨轮顺序固定为 \(\mathrm{UL} \to \mathrm{UR} \to \mathrm{DR} \to \mathrm{DL}\)。因此在第 \(i\) 组中:
| 组内位置 | 拨轮 |
|---|---|
| 第 1 列 | \(\mathrm{UL}\) |
| 第 2 列 | \(\mathrm{UR}\) |
| 第 3 列 | \(\mathrm{DR}\) |
| 第 4 列 | \(\mathrm{DL}\) |
二、生成算法
有了排列约定,生成 \(\mathbf{A}\) 的算法可以概括为三条流水线。
2.1 生成 UL 拨轮下的 16 个列向量
对第三篇中的 16 组按钮集,依次构造它们在 UL 拨轮下的效果向量:
输入: v0, v1, v2, v3, v4, v5 (6个原型向量)
C_op, D_op (对称变换函数)
步骤:
basis[0] = v0 ; basis[1] = C_op(v0)
basis[2] = v1 ; basis[3] = C_op(v1)
basis[4] = v2 ; basis[5] = C_op(v2)
basis[6] = D_op(v2) ; basis[7] = C_op(D_op(v2))
basis[8] = v3 ; basis[9] = C_op(v3)
basis[10] = v4 ; basis[11] = C_op(v4)
basis[12] = D_op(v4); basis[13] = C_op(D_op(v4))
basis[14] = v5 ; basis[15] = C_op(v5)
输出: basis[0..15] (16个18维向量, 对应 UL 拨轮)
2.2 扩展到 4 个拨轮
对于按钮集 \(S\),它在拨轮 \(R^k(\mathrm{UL})\) 下的效果向量可由对称性公式得到:
\\\mathbf{e}_{S,\\;R\^k(\\mathrm{UL})} = R\^{\\,k}\\!\\big(\\mathbf{e}_{R\^{-k}(S),\\;\\mathrm{UL}}\\big) \\pmod{12} \\
其中 \(R^{-k}(S)\) 表示将按钮集按逆方向旋转 \(k\) 步。
对于每个按钮集 S (k=0):
对于每个拨轮偏移 k ← 0, 1, 2, 3:
w ← R^k(UL) # 目标拨轮
S0 ← R^{-k}(S) # 按钮集逆旋转
vec ← basis[S0 对应的索引] # 查表 E(S0, UL)
col ← R^k_op(vec) mod 12 # 正向旋转
将 col 填入 A 的对应位置
2.3 三种变换函数的定义
为完成上述算法,需要定义三个变换函数。设 \(\mathbf{v} = (F_0,\dots,F_8,\; B_0,\dots,B_8)\) 是一个 18 维效果向量。
\(R^k\)(旋转 \(k \times 90^\circ\)) :正面顺时针 \(k \times 90^\circ\),反面逆时针 \(k \times 90^\circ\)。
\(C\)(正反互补) :按公式 \(C(F,\,B) = H(-B,\,-F)\) 计算,其中 \(H\) 为水平镜像(左右翻转),\(H(M){r,c}=M{r,\,2-c}\)。
\(D\)(对角镜像) :正面做转置 \(D(F){r,c} = F{c,r}\),反面做反对角转置 \(D(B){r,c} = B{2-c,\,2-r}\)。
三、程序实现
以下代码完整实现了上述算法。读者可以展开查看细节。
Python C MATLAB
python
import numpy as np
# ============================================================
# 辅助函数: 18维向量 ⇔ (正面3×3, 反面3×3)
# ============================================================
def to_matrices(v):
"""18维向量 → (正面3×3, 反面3×3)"""
return v[:9].reshape(3, 3), v[9:].reshape(3, 3)
def to_vector(F, B):
"""(正面3×3, 反面3×3) → 18维向量"""
return np.concatenate([F.flatten(), B.flatten()])
# ============================================================
# 变换算子
# ============================================================
def R_op(v, k=1):
"""旋转操作 R^k: 正面顺时针k×90°, 反面逆时针k×90°"""
F, B = to_matrices(v)
F_new = np.rot90(F, k=-int(k)) # CW = rot90(k=-1)
B_new = np.rot90(B, k=int(k)) # CCW = rot90(k=+1)
return to_vector(F_new, B_new)
def C_op(v):
"""正反互补: C(F,B) = H(-B, -F), 其中 H 为水平镜像(左右翻转)"""
F, B = to_matrices(v)
F_new = np.fliplr(-B) # H(-B): 反面取负后水平镜像 → 新正面
B_new = np.fliplr(-F) # H(-F): 正面取负后水平镜像 → 新反面
return to_vector(F_new, B_new)
def D_op(v):
"""对角镜像: 正面转置, 反面反对角转置"""
F, B = to_matrices(v)
F_new = F.T
B_new = np.rot90(B, k=2).T # 反对角转置 = 180°旋转后转置
return to_vector(F_new, B_new)
# ============================================================
# 6个原型效果向量 (mod 12, 负数已转为11)
# ============================================================
v0 = np.array([1,1,1,1,1,1,1,1,1, 11,0,11,0,0,0,11,0,11], dtype=int)
v1 = np.array([1,0,0,0,0,0,0,0,0, 0,11,11,0,11,11,0,0,0], dtype=int)
v2 = np.array([1,1,0,1,1,1,1,1,1, 0,0,11,0,0,0,11,0,11], dtype=int)
v3 = np.array([1,1,1,1,1,1,1,1,0, 11,0,11,0,0,0,0,0,11], dtype=int)
v4 = np.array([1,0,1,0,0,0,0,0,0, 11,11,11,11,11,11,0,0,0], dtype=int)
v5 = np.array([1,0,0,0,0,0,0,0,1, 0,11,11,11,11,11,11,11,0], dtype=int)
# ============================================================
# 步骤1: 生成UL拨轮下全部16种按钮状态的向量
# ============================================================
ul_vectors = []
ul_labels = []
def add_entry(label, vec):
ul_vectors.append(vec % 12)
ul_labels.append(label)
add_entry("∅", v0)
add_entry("{UL,UR,DL,DR}", C_op(v0))
add_entry("{UL}", v1)
add_entry("{UR,DL,DR}", C_op(v1))
add_entry("{UR}", v2)
add_entry("{UL,DL,DR}", C_op(v2))
add_entry("{DL}", D_op(v2))
add_entry("{UL,UR,DR}", C_op(D_op(v2)))
add_entry("{DR}", v3)
add_entry("{UL,UR,DL}", C_op(v3))
add_entry("{UL,UR}", v4)
add_entry("{DL,DR}", C_op(v4))
add_entry("{UL,DL}", D_op(v4))
add_entry("{UR,DR}", C_op(D_op(v4)))
add_entry("{UL,DR}", v5)
add_entry("{UR,DL}", C_op(v5))
# ============================================================
# 步骤2: 扩展到4个拨轮
# ============================================================
def rotate_bits(bits, k):
"""对4-bit整数左旋转k位 (k>0=R方向: UL→UR→DR→DL)"""
k = k % 4
return ((bits << k) | (bits >> (4 - k))) & 0xF
# 按钮集名称 → 4-bit编码 (bit0=UL, bit1=UR, bit2=DR, bit3=DL)
def set_to_bits(name):
mapping = {"UL": 0, "UR": 1, "DR": 2, "DL": 3}
bits = 0
for label, idx in mapping.items():
if label in name:
bits |= (1 << idx)
return bits
# 建立 UL 向量的查找表: bits → 向量
lookup = {}
for label, vec in zip(ul_labels, ul_vectors):
bits = set_to_bits(label)
lookup[bits] = vec
wheel_names = ["UL", "UR", "DR", "DL"]
A = np.zeros((18, 64), dtype=int)
col = 0
for label, vec_ul in zip(ul_labels, ul_vectors):
S_bits = set_to_bits(label)
for k, w_name in enumerate(wheel_names):
# 逆旋转按钮集: R^{-k}(S)
S0_bits = rotate_bits(S_bits, -k) # 等价于右旋转k位
vec_S0 = lookup[S0_bits] # E(R^{-k}(S), UL)
e_S_w = R_op(vec_S0, k) % 12 # R^k( E(R^{-k}(S), UL) )
A[:, col] = e_S_w
col += 1
print("矩阵 A 的规模:", A.shape)
print("✅ 生成完成")
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 18维向量类型: 正面3×3 (行优先) + 反面3×3 (行优先)
typedef int Vec18[18];
// ============================================================
// 3×3 矩阵操作
// ============================================================
// 旋转 k 次 (k>0=CCW, k<0=CW)
void rot90_3x3(const int src[9], int dst[9], int k) {
k = ((k % 4) + 4) % 4;
if (k == 0) { memcpy(dst, src, 9 * sizeof(int)); return; }
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++) {
switch (k) {
case 1: dst[(2-c)*3 + r] = src[r*3 + c]; break; // CCW 90°
case 2: dst[(2-r)*3 + (2-c)] = src[r*3 + c]; break; // 180°
case 3: dst[c*3 + (2-r)] = src[r*3 + c]; break; // CW 90°
}
}
}
void transpose_3x3(const int src[9], int dst[9]) {
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
dst[c*3 + r] = src[r*3 + c];
}
void fliplr_3x3(const int src[9], int dst[9]) {
for (int r = 0; r < 3; r++)
for (int c = 0; c < 3; c++)
dst[r*3 + (2-c)] = src[r*3 + c];
}
void neg_3x3(const int src[9], int dst[9]) {
for (int i = 0; i < 9; i++) dst[i] = (-src[i]) % 12;
}
void mod12_vec(Vec18 v) {
for (int i = 0; i < 18; i++)
v[i] = ((v[i] % 12) + 12) % 12;
}
// ============================================================
// 对称变换算子
// ============================================================
void R_op(const Vec18 v, Vec18 out, int k) {
int F[9], B[9], Fn[9], Bn[9];
memcpy(F, v, 9*sizeof(int));
memcpy(B, v+9, 9*sizeof(int));
rot90_3x3(F, Fn, -k); // 正面 CW
rot90_3x3(B, Bn, k); // 反面 CCW
memcpy(out, Fn, 9*sizeof(int));
memcpy(out+9, Bn, 9*sizeof(int));
}
void C_op(const Vec18 v, Vec18 out) {
int F[9], B[9], nF[9], nB[9];
memcpy(F, v, 9*sizeof(int));
memcpy(B, v+9, 9*sizeof(int));
neg_3x3(B, nB); fliplr_3x3(nB, out); // H(-B) → 新正面
neg_3x3(F, nF); fliplr_3x3(nF, out+9); // H(-F) → 新反面
}
void D_op(const Vec18 v, Vec18 out) {
int F[9], B[9], Fn[9], Bt[9], Bn[9];
memcpy(F, v, 9*sizeof(int));
memcpy(B, v+9, 9*sizeof(int));
transpose_3x3(F, Fn);
rot90_3x3(B, Bt, 2); transpose_3x3(Bt, Bn);
memcpy(out, Fn, 9*sizeof(int));
memcpy(out+9, Bn, 9*sizeof(int));
}
// ============================================================
// 位操作: 按钮集 ⇔ 4-bit 编码
// ============================================================
int label_to_bits(const char *label) {
int bits = 0;
if (strstr(label, "UL")) bits |= (1 << 0);
if (strstr(label, "UR")) bits |= (1 << 1);
if (strstr(label, "DR")) bits |= (1 << 2);
if (strstr(label, "DL")) bits |= (1 << 3);
return bits;
}
int rotate_bits(int bits, int k) {
k = ((k % 4) + 4) % 4;
return ((bits << k) | (bits >> (4 - k))) & 0xF;
}
// ============================================================
// 主程序
// ============================================================
int main() {
// 6 个原型效果向量 (mod 12, 负数已转为 11)
Vec18 v0 = {1,1,1,1,1,1,1,1,1, 11,0,11,0,0,0,11,0,11};
Vec18 v1 = {1,0,0,0,0,0,0,0,0, 0,11,11,0,11,11,0,0,0};
Vec18 v2 = {1,1,0,1,1,1,1,1,1, 0,0,11,0,0,0,11,0,11};
Vec18 v3 = {1,1,1,1,1,1,1,1,0, 11,0,11,0,0,0,0,0,11};
Vec18 v4 = {1,0,1,0,0,0,0,0,0, 11,11,11,11,11,11,0,0,0};
Vec18 v5 = {1,0,0,0,0,0,0,0,1, 0,11,11,11,11,11,11,11,0};
// ---- 步骤1: 生成 UL 拨轮下全部 16 种按钮状态的向量 ----
char *labels[16];
Vec18 ul_vecs[16];
Vec18 tmp;
#define ADD(idx, lbl, src) \
labels[idx] = lbl; \
memcpy(ul_vecs[idx], src, sizeof(Vec18)); \
mod12_vec(ul_vecs[idx]);
ADD(0, "∅", v0);
C_op(v0, tmp); ADD(1, "{UL,UR,DL,DR}", tmp);
ADD(2, "{UL}", v1);
C_op(v1, tmp); ADD(3, "{UR,DL,DR}", tmp);
ADD(4, "{UR}", v2);
C_op(v2, tmp); ADD(5, "{UL,DL,DR}", tmp);
D_op(v2, tmp); ADD(6, "{DL}", tmp);
C_op(tmp, tmp); ADD(7, "{UL,UR,DR}", tmp);
ADD(8, "{DR}", v3);
C_op(v3, tmp); ADD(9, "{UL,UR,DL}", tmp);
ADD(10, "{UL,UR}", v4);
C_op(v4, tmp); ADD(11, "{DL,DR}", tmp);
D_op(v4, tmp); ADD(12, "{UL,DL}", tmp);
C_op(tmp, tmp); ADD(13, "{UR,DR}", tmp);
ADD(14, "{UL,DR}", v5);
C_op(v5, tmp); ADD(15, "{UR,DL}", tmp);
#undef ADD
// 查找表: bits(0~15) → 向量
Vec18 lookup[16];
for (int i = 0; i < 16; i++) {
int bits = label_to_bits(labels[i]);
memcpy(lookup[bits], ul_vecs[i], sizeof(Vec18));
}
// ---- 步骤2: 扩展到 4 个拨轮 ----
const char *wheels[] = {"UL", "UR", "DR", "DL"};
int A[18][64];
int col = 0;
for (int i = 0; i < 16; i++) {
int S_bits = label_to_bits(labels[i]);
for (int k = 0; k < 4; k++) {
int S0_bits = rotate_bits(S_bits, -k); // R^{-k}(S)
Vec18 tmp2;
R_op(lookup[S0_bits], tmp2, k); // R^k( E(R^{-k}(S), UL) )
mod12_vec(tmp2);
for (int r = 0; r < 18; r++)
A[r][col] = tmp2[r];
col++;
}
}
printf("矩阵 A 的规模: 18 × %d\n", col);
printf("✅ 生成完成\n");
return 0;
}
matlab
% 生成魔表 18×64 操作矩阵 A (mod 12)
% 从 6 个原型向量出发,利用 R/D/C 对称算子扩展到全部 64 列
clear;
% ---- 6 个原型效果向量 (mod 12, 负数已转为 11) ----
v0 = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 11];
v1 = [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 0, 11, 11, 0, 0, 0];
v2 = [ 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 11];
v3 = [ 1, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 11, 0, 0, 0, 0, 0, 11];
v4 = [ 1, 0, 1, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0];
v5 = [ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 0];
% ---- 步骤 1: 生成 UL 拨轮下全部 16 种按钮状态的向量 ----
ul_labels = cell(1, 16);
ul_vecs = zeros(16, 18);
ul_labels{1} = '∅'; ul_vecs(1,:) = mod(v0, 12);
ul_labels{2} = '{UL,UR,DL,DR}'; ul_vecs(2,:) = mod(C_op(v0), 12);
ul_labels{3} = '{UL}'; ul_vecs(3,:) = mod(v1, 12);
ul_labels{4} = '{UR,DL,DR}'; ul_vecs(4,:) = mod(C_op(v1), 12);
ul_labels{5} = '{UR}'; ul_vecs(5,:) = mod(v2, 12);
ul_labels{6} = '{UL,DL,DR}'; ul_vecs(6,:) = mod(C_op(v2), 12);
ul_labels{7} = '{DL}'; ul_vecs(7,:) = mod(D_op(v2), 12);
ul_labels{8} = '{UL,UR,DR}'; ul_vecs(8,:) = mod(C_op(D_op(v2)), 12);
ul_labels{9} = '{DR}'; ul_vecs(9,:) = mod(v3, 12);
ul_labels{10} = '{UL,UR,DL}'; ul_vecs(10,:) = mod(C_op(v3), 12);
ul_labels{11} = '{UL,UR}'; ul_vecs(11,:) = mod(v4, 12);
ul_labels{12} = '{DL,DR}'; ul_vecs(12,:) = mod(C_op(v4), 12);
ul_labels{13} = '{UL,DL}'; ul_vecs(13,:) = mod(D_op(v4), 12);
ul_labels{14} = '{UR,DR}'; ul_vecs(14,:) = mod(C_op(D_op(v4)), 12);
ul_labels{15} = '{UL,DR}'; ul_vecs(15,:) = mod(v5, 12);
ul_labels{16} = '{UR,DL}'; ul_vecs(16,:) = mod(C_op(v5), 12);
% 查找表: bits(0~15) + 1 → 向量
lookup = cell(1, 16);
for i = 1:16
bits = label_to_bits(ul_labels{i});
lookup{bits + 1} = ul_vecs(i, :);
end
% ---- 步骤 2: 扩展到 4 个拨轮 ----
wheel_names = ["UL", "UR", "DR", "DL"];
A = zeros(18, 64);
col = 1;
for i = 1:16
S_bits = label_to_bits(ul_labels{i});
for k = 1:4
S0_bits = rotate_bits(S_bits, -(k - 1)); % R^{-k}(S)
A(:, col) = mod(R_op(lookup{S0_bits + 1}, k - 1), 12);
col = col + 1;
end
end
fprintf('矩阵 A 的规模: %d × %d\n', size(A, 1), size(A, 2));
fprintf('✅ 生成完成\n');
% ============================================================
% 局部函数
% ============================================================
function [F, B] = to_matrices(v)
% 18 向量 → 正面 3×3, 反面 3×3 (行优先等价于 Python reshape)
F = reshape(v(1:9), [3, 3]).';
B = reshape(v(10:18), [3, 3]).';
end
function v = to_vector(F, B)
v = [reshape(F.', [1, 9]), reshape(B.', [1, 9])];
end
function out = R_op(v, k)
[F, B] = to_matrices(v);
out = to_vector(rot90(F, -k), rot90(B, k));
end
function out = C_op(v)
[F, B] = to_matrices(v);
out = to_vector(fliplr(-B), fliplr(-F));
end
function out = D_op(v)
[F, B] = to_matrices(v);
out = to_vector(F.', rot90(B, 2).');
end
function bits = label_to_bits(s)
bits = uint32(0);
if contains(s, 'UL'), bits = bitor(bits, 1); end
if contains(s, 'UR'), bits = bitor(bits, 2); end
if contains(s, 'DR'), bits = bitor(bits, 4); end
if contains(s, 'DL'), bits = bitor(bits, 8); end
end
function out = rotate_bits(bits, k)
k = mod(k, 4);
if k == 0
out = bits;
else
b = uint32(bits);
left = bitand(bitshift(b, k), 15);
right = bitand(bitshift(b, k - 4), 15);
out = double(bitor(left, right));
end
end
注:此代码由 AI 辅助完成,已人工审查正确性。
四、矩阵 \(\mathbf{A}\) 的完整输出
展开下方可查看完整的 \(18 \times 64\) 矩阵。每行对应一个表盘指针,每列对应一种基本操作。
点击展开矩阵 A(18 行 × 64 列,mod 12)
列 1: ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 11) empty, UL
列 2: ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 11) empty, UR
列 3: ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 11) empty, DR
列 4: ( 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 11) empty, DL
列 5: ( 1, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 11) {UL,UR,DL,DR}, UL
列 6: ( 1, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 11) {UL,UR,DL,DR}, UR
列 7: ( 1, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 11) {UL,UR,DL,DR}, DR
列 8: ( 1, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 11) {UL,UR,DL,DR}, DL
列 9: ( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 0, 11, 11, 0, 0, 0) {UL}, UL
列10: ( 0, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 0, 0, 0, 0, 11, 0, 11) {UL}, UR
列11: ( 0, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 0, 0, 0, 0, 11, 0, 11) {UL}, DR
列12: ( 0, 1, 1, 1, 1, 1, 1, 1, 1, 11, 0, 0, 0, 0, 0, 11, 0, 11) {UL}, DL
列13: ( 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0) {UR,DL,DR}, UL
列14: ( 0, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 0, 11, 11, 11, 11, 11, 11) {UR,DL,DR}, UR
列15: ( 0, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 0, 11, 11, 11, 11, 11, 11) {UR,DL,DR}, DR
列16: ( 0, 0, 1, 0, 0, 0, 1, 0, 1, 11, 11, 0, 11, 11, 11, 11, 11, 11) {UR,DL,DR}, DL
列17: ( 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 11) {UR}, UL
列18: ( 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 11, 0, 11, 11, 0, 0, 0, 0) {UR}, UR
列19: ( 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 11) {UR}, DR
列20: ( 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 11) {UR}, DL
列21: ( 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 11) {UL,DL,DR}, UL
列22: ( 0, 1, 1, 0, 1, 1, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0) {UL,DL,DR}, UR
列23: ( 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 11) {UL,DL,DR}, DR
列24: ( 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 11) {UL,DL,DR}, DL
列25: ( 1, 1, 1, 1, 1, 1, 0, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 0) {DL}, UL
列26: ( 1, 1, 1, 1, 1, 1, 0, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 0) {DL}, UR
列27: ( 1, 1, 1, 1, 1, 1, 0, 1, 1, 11, 0, 11, 0, 0, 0, 11, 0, 0) {DL}, DR
列28: ( 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 11, 0, 11, 11) {DL}, DL
列29: ( 1, 0, 1, 0, 0, 0, 0, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 0) {UL,UR,DR}, UL
列30: ( 1, 0, 1, 0, 0, 0, 0, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 0) {UL,UR,DR}, UR
列31: ( 1, 0, 1, 0, 0, 0, 0, 0, 1, 11, 11, 11, 11, 11, 11, 11, 11, 0) {UL,UR,DR}, DR
列32: ( 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11) {UL,UR,DR}, DL
列33: ( 1, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 11, 0, 0, 0, 0, 0, 11) {DR}, UL
列34: ( 1, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 11, 0, 0, 0, 0, 0, 11) {DR}, UR
列35: ( 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 11, 11, 0, 11, 11, 0) {DR}, DR
列36: ( 1, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 11, 0, 0, 0, 0, 0, 11) {DR}, DL
列37: ( 1, 0, 1, 0, 0, 0, 1, 0, 0, 11, 11, 11, 11, 11, 11, 0, 11, 11) {UL,UR,DL}, UL
列38: ( 1, 0, 1, 0, 0, 0, 1, 0, 0, 11, 11, 11, 11, 11, 11, 0, 11, 11) {UL,UR,DL}, UR
列39: ( 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 11, 0, 0) {UL,UR,DL}, DR
列40: ( 1, 0, 1, 0, 0, 0, 1, 0, 0, 11, 11, 11, 11, 11, 11, 0, 11, 11) {UL,UR,DL}, DL
列41: ( 1, 0, 1, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0) {UL,UR}, UL
列42: ( 1, 0, 1, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 0, 0, 0) {UL,UR}, UR
列43: ( 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 11, 0, 11) {UL,UR}, DR
列44: ( 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 11, 0, 11) {UL,UR}, DL
列45: ( 1, 1, 1, 1, 1, 1, 0, 0, 0, 11, 0, 11, 0, 0, 0, 0, 0, 0) {DL,DR}, UL
列46: ( 1, 1, 1, 1, 1, 1, 0, 0, 0, 11, 0, 11, 0, 0, 0, 0, 0, 0) {DL,DR}, UR
列47: ( 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 11, 11, 11, 11, 11, 11) {DL,DR}, DR
列48: ( 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 11, 11, 11, 11, 11, 11) {DL,DR}, DL
列49: ( 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 11, 11, 0, 11, 11, 0, 11, 11) {UL,DL}, UL
列50: ( 0, 1, 1, 0, 1, 1, 0, 1, 1, 11, 0, 0, 0, 0, 0, 11, 0, 0) {UL,DL}, UR
列51: ( 0, 1, 1, 0, 1, 1, 0, 1, 1, 11, 0, 0, 0, 0, 0, 11, 0, 0) {UL,DL}, DR
列52: ( 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 11, 11, 0, 11, 11, 0, 11, 11) {UL,DL}, DL
列53: ( 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11) {UR,DR}, UL
列54: ( 0, 0, 1, 0, 0, 0, 0, 0, 1, 11, 11, 0, 11, 11, 0, 11, 11, 0) {UR,DR}, UR
列55: ( 0, 0, 1, 0, 0, 0, 0, 0, 1, 11, 11, 0, 11, 11, 0, 11, 11, 0) {UR,DR}, DR
列56: ( 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11) {UR,DR}, DL
列57: ( 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 0) {UL,DR}, UL
列58: ( 0, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11) {UL,DR}, UR
列59: ( 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 11, 11, 11, 11, 11, 11, 11, 0) {UL,DR}, DR
列60: ( 0, 1, 1, 1, 1, 1, 1, 1, 0, 11, 0, 0, 0, 0, 0, 0, 0, 11) {UL,DR}, DL
列61: ( 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 0) {UR,DL}, UL
列62: ( 0, 0, 1, 0, 0, 0, 1, 0, 0, 11, 11, 0, 11, 11, 11, 0, 11, 11) {UR,DL}, UR
列63: ( 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 11, 0, 0, 0, 11, 0, 0) {UR,DL}, DR
列64: ( 0, 0, 1, 0, 0, 0, 1, 0, 0, 11, 11, 0, 11, 11, 11, 0, 11, 11) {UR,DL}, DL
如下表所示,可直观查看完整的 \(18 \times 64\) 矩阵。

五、结语
本文完成了从 6 个原型到 \(\mathbf{A}\) 矩阵的完整生成过程:
- 排列约定:64 列按 16 组按钮集 × 4 个拨轮的有序排列,为后续分析建立统一坐标。
- 生成算法 :三步流水线------原型展开 16 个 UL 向量 → 查表加旋转扩展到 4 个拨轮 → 填满 \(\mathbf{A}\)。
- 程序实现 :给出了完整的 Python、C 及 MATLAB 代码,配合对称变换 \(R\)、\(C\)、\(D\) 的矩阵运算实现。
至此,魔表的数学模型从"纸面上的公式"走到了"可运行的代码"。
下一篇,我们将对 \(\mathbf{A}\) 进行深入的数学分析------秩、不变量、可达状态空间,真正理解这个 \(18 \times 64\) 矩阵背后的结构。