(小石头,站在偏数学的角度,来回答这个问题。简单一句话,魔方的原理就是:魔方群在状态集上的作用,具体回答如下:)
魔方群
整体来看,魔方(Rubik's cube)是一个立方体,一共有六个面 (surface),我们分别用 U(up 上)、D(down 下)、F (front 前)、B(back 后)、L(left 左)、R(right 右)来标识,不妨规定:U 对应 黄(yellow)、D 对应 白(white)、F 对应 蓝(blue)、B 对应 绿(green)、L 对应 橙(orange)、R 对应 红(red)。
令,M = {U, D, F, B, L, R},当 任意面 f ∈ M 朝向我们时,对 f 面 顺时针 旋转 90°, 被定义为 魔方的 基本操作(base operation),同样用 f 面 的 面标识 来表示 这种基本操作。所以 M 也代表 魔方的全部基本操作。
对于,任意 基本操作 g, h ∈ M,gh 称为 g 和 h 的 复合(compose), 表示 先 g 操作 再 h 操作 的复合操作。可以验证,复合满足结合律, 这样以来,以 M 为生成元 在复合操作下会生成一个群 G = (M),称为 魔方群(Rubik‘s cube group)。其中,G 的 幺元,记为 1, 表示 没有进行任何操作的操作。
什么是群?
群就是定义了一种运算 的集合 ,其 满足:
集合对运算封闭,即,对于任意 都有 ( 注意:和乘法运算类似,习惯省略不写 ) ;
运算有分配律,即, 对于任意 都有 ;
有幺元,即,存在 使得 对于 任意 都有 ;
有逆元,即,对于任意 都存在 的逆元 使得 。
什么是 M 生成的群?
数学上定义:包括 M 中元素的 最小的群,为M生成的群,记为 (M)。实际上,可以 对 M 中任意操作 g 和 h 不断的 进行 复合运算,如果得到的新复合操作 gh 不在 M 中,就 gh 添加到 M 里,直到 M 不再增加,这样就得到了 (M)。
同一基本操作 g, 连续四次 复合 就是 对 g 面 顺时针 旋转 360°,这相当于 没有操作,即,
gggg = 1
从而有:
gg³ = 1
也就是说 g³ 就是 g 的逆元 g⁻¹ ,相当于 对 g 面 逆时针 旋转 90°。
另外,由 gggg = 1 还可以得到:
g²g² = 1
这说明 连续两次 复合 g² 的逆元 就是自己,即,顺时针 旋转 180° 相当于 逆时针 旋转 180° 。
魔方状态
三阶魔方被细分为 3 × 3 × 3 = 27 个 立方小块(cubie)。其中,位于 中间核心的 那个 小块 不会受到 魔方操作 的影响到,而对于 每个 面中心的 那个 小块 魔方操作 同样无法改变它的位置,因此 魔方操作 所能 影响到的 小块 为 27 - (1 + 6) = 20 个。
这 20 个 受 魔方操作 作用的 小块,又分为 两类:
位于魔方 8 个角 处的 角(corner)块,它们有3个有效 小面(facet);
位于魔方 12 个棱 处的 棱(edge)块,它们有2个有效 小面;
由于,每个面的 中心块 保持位置不变,因此对于打乱的魔方,可以依照 中心块 来 确定 魔方的各个面 方向。魔方在初始(或 还原)状态下,角块 和 棱块 的每个 小面 和 该小面 所在面 的 中心小块 颜色保持一致。
我们用 角块(或 棱块) 的各小面 颜色所对应的 标识 的小写字母 的组合来标识 角块(或 棱块):
对于 角块,三个小面 x, y, z,有 6 种排列方式,这里 使用 从 u 或 d 开始 的 顺时针 排列方式,即,角块标识 xyz 保证 x = u/d 并且 x →y → z 是顺时针;
对于 棱块,二个小面 x, y, 有 2 种 排列方式,这里 使用 从 u 或 d(f 或 b) 开始 的 排列方式,即,棱块标识 xy 保证 x = u/d/f/b;
根据上面的规则,八个角块分别表示为:ufl, urf, ubr, ulb; dbl, dlf, dfr, drb; 十二个棱块分别表示为:ub, ur, uf, ul; bl, br, fr, fl; db, dr, df, dl
注意:六个中心块 分别表示为:u, d, f, b, l, r,核心块 一般用 o 表示 。
更进一步,对于角块 xyz,我们用 xyz 表示 x 小面,yzx 表示 y 小面,zxy 表示 z 小面,对于棱块 xy ,我们用 xy 表示 x 小面,用 yx 表示 y 小面,于是,我们就得到了 带有标注 的 8 × 3 + 12 × 2 = 48 个 小面。将,全体小面记为 T,则 任意 操作 g ∈ G 就变成了 T 上的 一种 置换(位置变换)。以 F 操作 为例,
观察发现, 小面 fur 经过 F 操作 置换 为 小面 flu,即,F(fur) = flu,另有 F(flu) = fdl、F(fdl) = frd、F(frd) = flu,于是 在 F 操作下,以上 4 个置换 形成了 一个 置换圈:
我们称其为 轮换(cycle),记为 (fur flu fdl frd) 。
参与轮换的 小面 可以是任意多个,值得注意的是:任何一个小面 a 的 轮换 (a) 相当于 不做 置换,有, 1 = () = (a) 。
当然,实际上 F 操作 包含 多个 轮换,将这些轮换 以复合的方式,聚合在一起,就是定义了一个 完整 F 操作:
F = (fur flu fdl frd) (fu fl fd fr)(rfu ufl lfd dfr)(rf uf lf df)(rdf urf luf dlf)
同理,我们可以将 其它魔方操作 定义为 轮换 的复合。
注意:为了方便,我们也可以用 1- 48 的 正整数,来替代 上面 S 中 对小面 的编码。
T 上的所有 置换函数,在函数复合下,组成 置换群 S₄₈。但是,因为 角块的面永远置换不到棱块的面,所以 G 仅仅是 S₄₈ 的子群。
用离散的小面来记录魔方的状态过于粗犷,重新审视魔方,我们会得到如下结果:
每个立方块都是一个整体,在任何魔方的操作下,组成它的小面不会分离;
每个立方块,有两种状态信息:位置 和 方向;
角块 和 棱块 在 魔法操作下 相互独立,即,角块 永远不可能 转到 棱块 上,反之亦然。
基于,以上分析,我们首先, 分别 对 角块 和 棱块 进行定位(location):
角块:ufl = 1, urf = 2, ubr = 3, ulb = 4; dbl = 5, dlf = 6, dfr = 7, drb = 8;
棱块:ub = 1, ur = 2, uf = 3, ul = 4; bl = 5, br = 6, fr = 7, fl = 8; db = 9, dr = 10, df = 11, dl = 12;
令 C = {1, 2, 3, 4, 5, 6, 7, 8}, 这里包含 所有 角块的位置信息,可以很容易将 基本操作 对 角块位置的 改变写成轮换形式:
U = (1 2 3 4),
D = (5 8 7 6),
F = (1 6 7 2),
B = (3 8 5 4),
L = (1 4 5 6),
R = (2 7 8 3)
显然,G 作用在 C 上 是 置换群 S₈ 的子群。
同理,令 E = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},基本操作对于 棱块 位置的改变写成轮换形式为:
U = (1 4 3 2),
D = (9 10 11 12),
F = (3 8 11 7),
B = (1 6 9 5),
L = (4 5 12 8),
R = (2 7 10 6)
同样,G 作用在 E 上 是 置换群 S₁₂ 的子群。
然后,我们分别对 角块 和 棱块 进行定向(orientation):
角块:u/d 为定向面,xyz = 012;
棱块:u/d/f/b 为定向面,xy = 01;
对于保持 定向 信息,我们只需要定义,定位位置 当前 立方块 的 定向面 对应 的 编号就可以了。而对于 基本操作,对 定向的 改变,我们也只需要 记录,原始状态下,经过 基本操作后,各个 定位位置,的 定向面 对应 的 编号就可以了。如果,原始状态下,即, 定向面的编号为 0,经过某操作,到新位置后,定向面编号为 n,则 原来 定向面的编号为 m,经同样操作,到新位置后,定向面编号就是 (n + m) mod k,对于角块 k = 3,对于 棱块 k = 2。0- 不旋转,1-逆时针旋转,2-顺时针旋转。
令,V = (0, 0, 0, 0, 0, 0, 0, 0) 表示 角块的所有定向,则 基本操作为对角块定向的改变为:
U = (0, 0, 0, 0, 0, 0, 0, 0),
D = (0, 0, 0, 0, 0, 0, 0, 0),
F = (1, 2, 0, 0, 0, 2, 1, 0),
B = (0, 0, 1, 2, 1, 0, 0, 2),
L = (2, 0, 0, 1, 2, 1, 0, 0),
R = (0, 1, 2, 0, 0, 0, 2, 1)
对于每一位来说都是 Z₃ ,总共 8 个 Z₃ 就是 Z₃⁸ ,但是 考虑 在 到 7 个 角块固定的情况下,我们无法 单独 旋转 剩下的那个,因此 G 在 V 上的作用 实际上 是 Z₃⁷。
令,W = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) 表示 棱块的所有定向,则 基本操作为对棱块定向的改变为:
U = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
D = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
F = (0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0),
B = (1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0),
L = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
R = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
同理, G 在 W 上的作用 是 Z₂¹¹。
当以上编号混合在一起使用时,为了区分,分别用 c、e、v、w 作为 角块定位、棱块定位、角块定向、棱块定向 编号的前缀,并将编号写成下标。例如:
F = (c₁ c₆ c₇ c₂) (e₃ e₈ e₁₁ e₇) (v₁, v₂, v₀, v₀, v₀, v₂, v₁, v₀) (w₀, w₀, w₁, w₀, w₀, w₀, w₁, w₁, w₀, w₀, w₁, w₀)
辅助工具
在进行下一步分析之前,我们先编写一点 JavaScript 代码,以帮助我们,对 G 中的 操作进行复合。
魔方状态(state)的 格式为:
state:[[角块定位], [棱块定位], [角块定向], 棱块定向]
声明 魔方初始状态 s₀ 如下:
魔方操作(operation)的 格式为:
[[[角块轮换], ...], [[棱块轮换], ...], [角块旋转], [棱块旋转]]
基本操作声明如下:
声明,在给定状态上执行魔方操作的函数:
声明,从给定状态中分析出魔方操作的函数:
定义 复合 函数:
为了输出简洁,当所有角块(或,棱块)不发生旋转 时,用一对空括号表示。
最后,我们对基本操作进行必要的扩展:
换位子 和 共轭
对于 任意两个 魔方操作 g,h ∈ G,如果,g 和 h 的复合 满足交换律,则:
gh = hg
等式两边右乘 g⁻¹h⁻¹,有:
ghg⁻¹h⁻¹ = hgg⁻¹h⁻¹ = h1h⁻¹ = hh⁻¹ = 1
如果 不满足交换律,则:
ghg⁻¹h⁻¹ ≠ 1
令,[g, h] = ghg⁻¹h⁻¹,称其为 换位子(commutator)。
一般来说,魔方相对面 ,如: F 和 B,U 和 D,L 和 R 之间是可以交换的,即,
[F, B] = [U, D] = [L, R] = 1
所有,换位子 之间是可以交换的,即:
[[g₁, h₁] [g₂, h₂]] = 1
关于,换位子有 性质1:如果 g 和 h 两种操作,只 共同影响 一个 小块 k,其中 g 为 n → k,h 为 m → k,则有 [g, h] = (k, n, m),[h, g] = (k, m, n)。
例如,若 g = (c₁ c₂ c₃), h = (c₁, c₄ c₅),则 k = c₁, n = c₂, m = c₄,于是有:
即,[g, h] = (c₁ c₂ c₄),[h, g] = (c₁ c₄ c₂)。
性质1推论:如果 g 和 h 两种操作,共同影响 的小块,刚好 在 g 和 h 中 分别 形成 轮换 σ 和 τ,则有 [g, h] = [σ, τ]。
例如:若 g = (c₁ c₂ c₃ c₄)(c₅ c₆), h = (c₁ c₂ c₄ c₃)(c₇ c₈),则 它们的共同影响小块 c₁、c₂、c₃、c₄,分别 在 g 和 h 中,组成轮转 (c₁ c₂ c₃ c₄) 和 (c₁ c₂ c₄ c₃),于是有:
即,[g, h] = [(c₁ c₂ c₃ c₄), (c₁ c₂ c₄ c₃)]。
魔方群中还有另外一种 称为 共轭(conjugate)的复合方式:对于 任何操作 g,h ∈ G,称 ghg⁻¹ 为 h 关于 g 的共轭。
共轭具有 性质2:如果 h = (a b c) 而 g 将 A, B, C 分别映射到 a, b, c,则有 ghg⁻¹ = (A B C)。
例如:若 h = (c₁ c₂ c₃), g = (c₁ c₄)(c₂ c₅)(c₃ c₆),则有:
即,ghg⁻¹ = (c₄ c₅ c₆)。
魔方公式
好了!现在利用上面的知识,就可以开始构造魔方公式了。
寻找角块的换位公式
我们发现 B⁻¹ 关于 R⁻¹ 的 共轭 R⁻¹B⁻¹(R⁻¹)⁻¹ = R⁻¹B⁻¹R:
和 F²:
仅有 c₇ 共同影响,于是它们满足 性质1,有:
即,[R⁻¹B⁻¹R, F²] = R⁻¹B⁻¹R F² (R⁻¹B⁻¹R)⁻¹ (F²)⁻¹ = R⁻¹B⁻¹R F² R⁻¹B⁻¹R F² = (c1, c7, c8)。
注意:因为 (ab)(b⁻¹a⁻¹) = abb⁻¹a⁻¹ = a1a⁻¹ = aa⁻¹ = 1,所以 (ab)⁻¹ = b⁻¹a⁻¹。
这里 c₁, c₇, c₈ 不共面,考虑 R² :
刚好 将 1 ↦ 1, 2 ↦ 8, 3 ↦ 7,于是根据 性质2,有:
开头的 RR RRR = R ,于是最终得到 公式C:
即,
R²[R⁻¹B⁻¹R, F²]R⁻² = RB⁻¹RF²R⁻¹BRF²R² = (c₁ c₂ c₃)
寻找棱块的换位公式
我们定义一种新的操作 M:面对 F 面,顺指针旋转 F 和 B 面之间那个中间的面M。M 操作 只改变棱块:
我们发现 M(或 M)与 U²:
共同影响 e₄,因此 根据性质1,[M⁻¹, U²] 构成三轮换:
即,[M⁻¹, U²] = M⁻¹U²MU² = (e₂ e₄ e₁₀)。
其实,M⁻¹ 就相当于 FB⁻¹ 的复合,只不过,在执行 M⁻¹ 后,还做了 R 面朝向了 U 的动作。
这时 执行 U² 相当于 执行 R²,于是翻译为 基本操作 [M⁻¹, U²] = FB⁻¹R²BF⁻¹U²,验证:
最后, 根据 性质2,利用 R²U 将 这个 三轮换,换到同一个面上:
倒数第2, 3 项合并后,就得到了 公式D:
R²U[M⁻¹, U²]U⁻¹R² = R²UFB⁻¹R²BF⁻¹UR² = (e₁ e₃ e₂)
寻找角块的旋转公式
观察 D² 关于 RF⁻¹ 的共轭 RF⁻¹D²FR⁻¹:
它们,有共同的轮转 (c₁ c₃),于是根据 性质1推论,有:
[U², RF⁻¹D²FR⁻¹] = [(c₁ c₃), (c₁ c₃)] = (c₁ c₃)(c₁ c₃)(c₃, c₁)(c₃, c₁) = (c₁ c₃)1(c₃, c₁) = (c₁ c₃)(c₃, c₁) = 1
这样以来,[U², RF⁻¹D²FR⁻¹] 就没有了位置变换,仅仅剩下的就是旋转:
于是,我们就得到 公式 E:
[U², RF⁻¹D²FR⁻¹] = U²RF⁻¹D²FR⁻¹U²RF⁻¹D²FR⁻¹ = (v₁, v₀, v₂, v₀, v₀, v₀, v₀, v₀);
公式 E 分别 对 c₁ 和 c₃ 进行 逆时针 和 顺时针 旋转。
寻找棱块的旋转公式
M 和 U 分别执行4次会恢复,那么 MU 执行四次,即,(MU)⁴ 是什么呢?
我们神奇的发现:
(MU)⁴ = F⁻¹BLF⁻¹BDF⁻¹BRF⁻¹BU = (w₁, w₁, w₀, w₀, w₀, w₀, w₀, w₀, w₀, w₁, w₀, w₁)
即,(MU)⁴ 只对 e₁, e₂, e₁0, e₁₂ 旋转;
同样,(MU⁻¹)⁴ :
(MU⁻¹)⁴ = F⁻¹BL⁻¹F⁻¹BD⁻¹F⁻¹BR⁻¹F⁻¹BU⁻¹ = (w₀, w₁, w₁, w₀, w₀, w₀, w₀, w₀, w₁, w₀, w₁)
即,(MU⁻¹)⁴ 只对 e₂, e3, e₁0, e₁₂ 旋转;
因为 棱块旋转 2 次就等于没有旋转,于是 (MU)⁴ 和 (MU⁻¹)⁴ 的复合 结果 只对 e₁ 和 e₃ 进行旋转,这就是 公式F:
(MU)⁴(MU⁻¹)⁴ = (w₁,w₀, w₁, w₀, w₀, w₀, w₀, w₀, w₀, w₀, w₀)
可以验证:
暴力搜索
两轮换 称为 对换,在魔方群中 单独的 对换操作,是不可能的 因此 三轮换,成立 公式构造的 关键,除了上面利用 性质1 来 找寻 三轮换 的 方法为,我们还可以用计算机,进行暴力搜索。例如:在 2 个 R,3 个 R⁻¹, 3 个 U, 2 个 U⁻¹ 的全排列中,进行三轮换搜索:
我们得到:
即,R⁻¹U⁻¹RURURU⁻¹R⁻¹U⁻¹ = (e₃ e₄ e₁₀)。然后 根据 性质2,利用 R² 将 这个 三轮换,换到同一个面上:
同样,将开头的 5 个 R 合并,就得到 和 公式D 类似的公式:
RU⁻¹RURURU⁻¹R⁻¹U⁻¹R² = (e₂ e₃ e₄)
对于旋转来说,以上的分析,最少只能的道 两个 角块(或 棱块)的旋转,我们无法做到 仅仅旋转 一个角块(或 棱块)。
上面,给定的公式都保证 角块(或 棱块)的旋转 时,所有小块位置不变,但 实际上,不一定需要这么严格,我们可以允许 与旋转小块同处一个面 内 小块的位置变换。通过暴力搜索,我们得到了公式B:
即,
RUR⁻¹URU²R⁻¹ = (c₁ c₃)(c₂ c₄)(e₁ e₂ e₄)(v₂, v₂, v₀, v₂, v₀, v₀, v₀, v₀);
以及,公式A:
即,
FRUR⁻¹U⁻¹F⁻¹ = (c₁ c₂)(c₃ c₄)(e₁ e₂ e₃)(v₀, v₂, v₁, v₀, v₀, v₀, v₀, v₀)(w₀, w₁, w₁, w₀, w₀, w₀, w₀, w₀, w₀, w₀, w₀, w₀);
公式 AB 都是 只 改变 顶层 位置的 操作。
其实,公式A就是 F[R, U]F⁻¹,其中 [R, U]:
[R, U] 的功效是 (e₁ e₂ e₇) ,即,将 顶层棱块 e₁ e₂ 和 中层 棱块 e₇ 轮换,但副作用 (c₂ c₇) 变动了 底层。不过幸运的是,我们找到了 [F⁻¹, U⁻¹]:
[ F⁻¹, U⁻¹] 的功效 和 [R, U] 类似,而其副作也是 (c₂ c₇)。因为 (c₂ c₇)(c₂ c₇) = 1,所以 [U⁻¹, F⁻¹] 的 刚好可以抵消 [R, U] 的副作用。于是,我们就得到了 公式A的附带公式:
[R, U] [ F⁻¹, U⁻¹] 和 [ F⁻¹, U⁻¹] [R, U]
功效分别是 (e₁ e₂ e₇ e₄ e₃) 和 (e₁ e₂ e₃ e₄ e₇),即,将顶层的 四个棱块 与 中层 的 棱块 e₇ 轮转。
在魔方数学原理的指导下,通过这种计算机暴力搜索的方式,我们还可以找到很多有用的公式,目前紧紧OLL公式就有 57 个,而更多的复杂公式几百上千。
众所周知的 ”七步公式还原法“(层先法) 就包括了从这些公式中选出来的 一组基础公式(包括上面提到的 公式ABCD)。(七步公式还原法,已经有条友在回答中详细介绍过了,我这里就不累述了。)
不知不觉,已经写了 5千余字了。关于魔法群还有很多更深入的内容,例如:上帝数 等,由于篇幅有限,这里不能一一展开,以后有机会再说。
(小石头,数学水平有限,出错在所难免,希望各位老师和同学批评指正。)
(补充 2019/10/30)
我将辅助工具的代码放在这里,以便想要自己试验的条友复制粘贴。
运行环境:chrome 浏览器;
文件名:rc.html,包含代码:
<script>
const s0 = [[1, 2, 3, 4, 5, 6, 7, 8],
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
const U = [[[1, 2, 3, 4]],[[1, 4, 3, 2]], [0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
const D = [[[5, 8, 7, 6]],[[9, 10, 11, 12]],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
const F = [[[1, 6, 7, 2]],[[3, 8, 11, 7]], [1, 2, 0, 0, 0, 2, 1, 0],[0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]];
const B = [[[3, 8, 5, 4]],[[1, 6, 9, 5]], [0, 0, 1, 2, 1, 0, 0, 2],[1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0]];
const L = [[[1, 4, 5, 6]],[[4, 5, 12, 8]], [2, 0, 0, 1, 2, 1, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
const R = [[[2, 7, 8, 3]],[[2, 7, 10, 6]], [0, 1, 2, 0, 0, 0, 2, 1],[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
function perform(state, ... operations) {
for(var g of operations) {
var newstate = [g[0].reduce((l, c) => permute(l, c), state[0]),
g[1].reduce((l, c) => permute(l, c), state[1])];
newstate[2] = turn(state[0], state[2], newstate[0], g[2], 3);
newstate[3] = turn(state[1], state[3], newstate[1], g[3], 2);
state = newstate;
}
return state;
}
function permute(location, cycle) {
var newlocation = Array.from(location);
for(var i = 0; i < cycle.length - 1; i++) {
newlocation[cycle[i] - 1] = newlocation[cycle[i+1] - 1];
}
newlocation[cycle[cycle.length - 1] - 1] = location[cycle[0] - 1];
return newlocation ;
}
function turn(oldlocation, oldorientation, newlocation, spin, mod) {
var neworientation = [];
for (var i = 0; i < newlocation.length; i++) {
var j = oldlocation.indexOf(newlocation[i]);
neworientation[i] = (oldorientation[j] + spin[i]) % mod;
}
return neworientation;
}
function parse(state) {
return [parse_cycle(state[0]), parse_cycle(state[1]),
Array.from(state[2]), Array.from(state[3])
];
}
function parse_cycle(location) {
var flags = [], cycles = [];
for (var i = 0; i < location.length; i ++) {
if (i + 1 != location[i] && !flags[i]) {
var cycle = [i + 1, location[i]], j = location[i] - 1;
while(true) {
flags[j] = 1;
if (location[j] == i + 1)
break;
cycle.push(location[j]);
j = location[j] - 1;
}
cycles.push(cycle);
}
}
return cycles;
}
function compose(... operations) {
return parse(perform(s0, ... operations));
}
const str = arr => arr.reduce((s, x) => s +
(x[0] instanceof Array ? '[(' + x.map(y => y.join(' ')).join(')(') + ')]' :
(x.length == 0 ? '[]' : '(' + x.join() + ')')), '')
.replace('(0,0,0,0,0,0,0,0)', '()')
.replace('(0,0,0,0,0,0,0,0,0,0,0,0)', '()');
const c = (... ops) => str(compose(... ops));
const UU = compose(U, U), UUU = compose(U, U, U);
const DD = compose(D, D), DDD = compose(D, D, D);
const FF = compose(F, F), FFF = compose(F, F, F);
const BB = compose(B, B), BBB = compose(B, B, B);
const LL = compose(L, L), LLL = compose(L, L, L);
const RR = compose(R, R), RRR = compose(R, R, R);
const cycle = (... x) => [[x], [], s0[2], s0[3]];
const M = [[],[[2,4,12,10]],[0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]];
const MMM = compose(M, M, M);
function perm(arr, callback, index){
var swap = (a, i, j, t) => (t = a[i], a[i] = a[j], a[j] = t);
index = index || 0;
if (index < arr.length) {
for (var j = index; j < arr.length; j++) {
swap(arr, index, j);
if (perm(arr, callback, index + 1)) return true;
swap(arr, index, j);
}
}
else {
return callback(arr);
}
}
</script>
文件名:rc2.html,包含代码:
<script>function perm(arr, callback, index){ var swap = (a, i, j, t) => (t = a[i], a[i] = a[j], a[j] = t); index = index || 0; if (index < arr.length) { for (var j = index; j < arr.length; j++) { swap(arr, index, j); if (perm(arr, callback, index + 1)) return true; swap(arr, index, j); } } else { return callback(arr); }}R._tag = 'R'; RRR._tag = 'R⁻¹'; U._tag = 'U', UUU._tag = 'U⁻¹';perm([RRR, UUU, R, U, RRR, UUU, R, U, R, UUU], x => { var g = compose(... x); console.log('+'); if (g[0].length == 0 && g[1].length == 1 && g[1][0].length == 3 && g[2].toString() == s0[2].toString() && g[3].toString() == s0[3].toString()) { console.log(x.reduce((y, z) => y + z._tag, '')); return true; }});</script>
联系客服