3×3魔方公式说明书图纸第一层(3×3魔方公式说明书新手入门)

儿童节刚刚过去,本期文章我们谈谈童年回(噩)忆(梦)中的魔方

也许这是一个略显愚蠢的问题:为什么一个完好的魔方总是可以恢复原样?这其实是一个既简单又深刻的问题。

答:魔方的每个状态都是由初始状态通过一系列有限的操作所得到的,这些操作包括(顺时针旋转上层四分之一周)、(顺时针旋转前层四分之一周)、(顺时针旋转右层四分之一周)……那我们只需要“原路返回”,不就可以回到起点了吗?

x3魔方公式说明书图纸第一层(3x3魔方公式说明书新手入门)"x3魔方公式说明书图纸第一层(3x3魔方公式说明书新手入门)"

例如我们对魔方进行操作:,那么我们只需要再进行如下操作即可:

其中表示的反向操作,即「逆时针」旋转前层四分之一周,其余符号同理。不过按照魔方术语,往往用其小写字母表示,即。

群论中,称为的「逆」,因为他们的复合的结果是单位元,即魔方会回到初始状况:

群的复合运算满足「结合律」,容易给出上面等式成立的证明:

一个代数系统如果满足三条性质,则称为群:

  • 存在单位元;
  • 存在逆元;
  • 满足结合律。

可见魔方确实是一个实实在在的「有限群(Finite group)」

为什么说它有限呢?因为它是「置换群(Permutation group)」「子群(Subgroup)」置换群是有限群,而它的子群是由其元素的子集构成的更小的群,所以其子群也一定是有限群。

所谓置换群,用魔方来讲就是:魔方的所有状态构成一个有限集合。状态与状态之间的转移,就是群的元素。一个的魔方有6个面,每个面又分为9个小的块面,于是一共有54个小的块面。这些小的块面的颜色共同构成魔方的当前状态,如果这54个块面可以随意互换位置,那么构成的群我们记为。然而魔方由于其特殊的内部构造,使得这种随意性是不可能发生的,真实的情况则是的一个子群,我们称为魔方群(Rubik’ Cube group)」

这个群的实际状态数已被数学家给出,它是一个巨大的数字:

大约是目前地球人口的平方。

有限,但是太大了。所以回答有没有魔方还原策略还远远不够。我们更关心的是魔方能否快速还原。或者我们更进一步:还原一个魔方需要几个步骤?

答:20步!

这个结果叫做神数。类似于平面图四色定理的证明(给没有飞地的地图着色使邻国颜色不同,只用四种颜色就够了),也是用计算机暴力证明的。

这么多,这么少!

这意味着什么呢?说明魔方的各个状态高度关联,所有的状态统统被压缩在直径为20的高维球体内。

x3魔方公式说明书图纸第一层(3x3魔方公式说明书新手入门)"

通常购买魔方会附有说明书,说明书中介绍了还原魔方的配方。在应用这些公式时,我们似乎不需要关注每一个面片的状态,往往会“糊里糊涂”地还原魔方,知其然而不知其所以然。而且还原步骤的数量往往超过20步,也就是说这些公式有一些“弯路”。

我们如何理解魔方的归约公式?

我们可以用图论来表示魔方组:每个状态记录为一个节点。如果有一个变换,可以从这个状态得到另一个状态,那么这两个节点一定是通过一条边连接起来的,这样我们就得到一个关于魔方状态的网络。在这个网络中,新手寻找最佳路线是不切实际的,归约公式帮助我们进入一个特定的轨迹。这条赛道就像一个时钟表盘,赛道上的每个状态就像表盘上的刻度。魔方的初始状态是这个表盘上的12点,只要我们按照顺时针(逆时针)方向走,就一定会通过我们的目标。

x3魔方公式说明书图纸第一层(3x3魔方公式说明书新手入门)"

魔方群中这种类似于表盘结构的子群,我们称之为「循环群(Cyclic group)」,并且是有限循环群。

而魔方还原公式本身的结构也非常耐人寻味,例如

在群论中我们称之为的「共轭(Conjugate)」。在还原魔方的时候,我们往往会遇到这样的窘境:我们想让和交换,然而两者直接交换会影响到,然而我们并不想让发生改变……这个时候我们就利用和去消弭掉所带来的影响。与共轭的原理类似,我们还会用到「交换子(Commutator)」,形如。前文我们在定义群的时候,只提及了结合律而没有提及交换律,这是因为有大量的群是非交换的,例如矩阵群。交换群是没有所谓交换子的,这是因为

在某种意义上,交换子群(由交换子生成的群)提供了群的可交换程度。一个群内可交换的元素越多,交换子就越少,交换子群也就越小。

关于魔方的具体内容请读者参考《Group Theory via Rubik’s Cube》(链接:http://geometer.org/rubik/group.pdf)。另外提供一个在线魔方的程序(链接:https://iamthecu.be),非常精美有趣。

R语言程序

下面是我写的2阶魔方的平面展开图,给定操作自动演算出结果。

x3魔方公式说明书图纸第一层(3x3魔方公式说明书新手入门)"

代码说明:

  • 代码中两个变换的乘法表示先执行再执行,这虽然与映射复合的乘法规则相反,但是符合我们从左往右的阅读习惯。

  • 最后一行代码

  • 倒数第三行(括号不算)的代码,我为了做演示视频,有意设置了延迟效果。如果网友想要快速得到结果,可以删掉这行代码。

####2阶魔方
#矩阵中心对称
o <- function(A)
{
t=A[1,1]
A[1,1]=A[2,2]
A[2,2]=t
t=A[1,2]
A[1,2]=A[2,1]
A[2,1]=t
A
}
#矩阵元素逆时针旋转
r <- function(A)
{
t=A[1,1]
A[1,1]=A[1,2]
A[1,2]=A[2,2]
A[2,2]=A[2,1]
A[2,1]=t
A
}

#矩阵元素顺时针旋转
v <- function(A)
{
t=A[1,1]
A[1,1]=A[2,1]
A[2,1]=A[2,2]
A[2,2]=A[1,2]
A[1,2]=t
A
}

#魔方的六个面
A=matrix(rep(1,4),2)
B=matrix(rep(2,4),2)
C=matrix(rep(3,4),2)
a=matrix(rep(4,4),2)
b=matrix(rep(5,4),2)
c=matrix(rep(6,4),2)

#A为俯视图,B为正视图,C为右侧视图,X=A,B,C;结果为矩阵形式,方便绘图。
Xup <- function(A,a,B,b,C,c)
{
Aup=matrix(rep(0,48),6)
Aup[3:4,5:6]=A
Aup[3:4,1:2]=a
Aup[1:2,5:6]=B
Aup[5:6,5:6]=b
Aup[3:4,3:4]=C
Aup[3:4,7:8]=c
Aup
}

cube=list(A,a,B,b,C,c)
cube[[7]]=Xup(A,a,B,b,C,c)


#B朝上的十字架展开图(A --> B),输入输出皆为列表
ABup <- function(Aup)
{
Bup=list
Bup[[1]]=Aup[[1]]
Bup[[2]]=o(Aup[[2]])
Bup[[3]]=Aup[[3]]
Bup[[4]]=o(Aup[[4]])
Bup[[5]]=v(Aup[[5]])
Bup[[6]]=r(Aup[[6]])
Bup[[7]]=Xup(Bup[[3]],Bup[[4]],Bup[[2]],
Bup[[1]],Bup[[5]],Bup[[6]])
Bup
}

#(B --> A)
BAup <- function(Bup)
{
Aup=list
Aup[[1]]=Bup[[1]]
Aup[[2]]=o(Bup[[2]])
Aup[[3]]=Bup[[3]]
Aup[[4]]=o(Bup[[4]])
Aup[[5]]=r(Bup[[5]])
Aup[[6]]=v(Bup[[6]])
Aup[[7]]=Xup(Aup[[1]],Aup[[2]],Aup[[3]],
Aup[[4]],Aup[[5]],Aup[[6]])
Aup
}

#C朝上的十字架展开图(A --> C)
ACup <- function(Aup)
{
Cup=list
Cup[[1]]=Aup[[1]]
Cup[[2]]=Aup[[2]]
Cup[[3]]=r(Aup[[3]])
Cup[[4]]=v(Aup[[4]])
Cup[[5]]=Aup[[5]]
Cup[[6]]=Aup[[6]]
Cup[[7]]=Xup(Cup[[5]],Cup[[6]],Cup[[3]],
Cup[[4]],Cup[[2]],Cup[[1]])
Cup
}

#(C --> A)
CAup <- function(Cup)
{
Aup=list
Aup[[1]]=Cup[[1]]
Aup[[2]]=Cup[[2]]
Aup[[3]]=v(Cup[[3]])
Aup[[4]]=r(Cup[[4]])
Aup[[5]]=Cup[[5]]
Aup[[6]]=Cup[[6]]
Aup[[7]]=Xup(Aup[[1]],Aup[[2]],Aup[[3]],
Aup[[4]],Aup[[5]],Aup[[6]])
Aup
}


#画出魔方展开图
color=c("white","red","orange","yellow","green","blue","purple")
par(mai=rep(0,4),oma=rep(0,4))
plot(0,0, type="n", xlim=c(0,7), ylim=c(0,9))
draw <- function(Cube) #输入矩阵
{
for(i in 1:6)for(j in 1:8)points(i, j, pch=15, cex=4, col=color[Cube[i,j]+1])
}
draw(Xup(A,a,B,b,C,c)) #魔方初始状态

##三大变换
#对A(红色面)逆时针旋转90度;此时List应该是A面为俯视面的形式
U <- function(List)
{
unfold=Xup(List[[1]],List[[2]],List[[3]],
List[[4]],List[[5]],List[[6]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7) A[9-j,2+i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
A=unfold[3:4,5:6]
a=unfold[3:4,1:2]
B=unfold[1:2,5:6]
b=unfold[5:6,5:6]
C=unfold[3:4,3:4]
c=unfold[3:4,7:8]
List=list(A,a,B,b,C,c,unfold)
List
}

#U的逆变换,此时List应该是A面为俯视面的形式
V <- function(List)
{
unfold=Xup(List[[1]],List[[2]],List[[3]],
List[[4]],List[[5]],List[[6]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7) A[j-2,9-i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
A=unfold[3:4,5:6]
a=unfold[3:4,1:2]
B=unfold[1:2,5:6]
b=unfold[5:6,5:6]
C=unfold[3:4,3:4]
c=unfold[3:4,7:8]
List=list(A,a,B,b,C,c,unfold)
List
}

#对B(橙色面)逆时针旋转90度;此时List应该是B面为俯视面的形式
F <- function(List)
{
unfold=Xup(List[[3]],List[[4]],List[[2]],
List[[1]],List[[5]],List[[6]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7)A[9-j,2+i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
B=unfold[3:4,5:6]
b=unfold[3:4,1:2]
a=unfold[1:2,5:6]
A=unfold[5:6,5:6]
C=unfold[3:4,3:4]
c=unfold[3:4,7:8]
List=list(A,a,B,b,C,c,unfold)
List
}

#F的逆变换,此时List应该是B面为俯视面的形式
E <- function(List)
{
unfold=Xup(List[[3]],List[[4]],List[[2]],
List[[1]],List[[5]],List[[6]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7)A[j-2,9-i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
B=unfold[3:4,5:6]
b=unfold[3:4,1:2]
a=unfold[1:2,5:6]
A=unfold[5:6,5:6]
C=unfold[3:4,3:4]
c=unfold[3:4,7:8]
List=list(A,a,B,b,C,c,unfold)
List
}

#对C(黄色面)逆时针旋转90度;此时List应该是C面为俯视面的形式
R <- function(List)
{
unfold=Xup(List[[5]],List[[6]],List[[3]],
List[[4]],List[[2]],List[[1]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7)A[9-j,2+i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
C=unfold[3:4,5:6]
c=unfold[3:4,1:2]
B=unfold[1:2,5:6]
b=unfold[5:6,5:6]
A=unfold[3:4,7:8]
a=unfold[3:4,3:4]
List=list(A,a,B,b,C,c,unfold)
List
}
#R的逆变换,此时List应该是C面为俯视面的形式
K <- function(List)
{
unfold=Xup(List[[5]],List[[6]],List[[3]],
List[[4]],List[[2]],List[[1]])
A=matrix(rep(0,48),6)
for(i in 2:5)for(j in 4:7)A[j-2,9-i]=unfold[i,j] #坐标旋转由复数推导
unfold[2:5,4:7]=A[2:5,4:7]
C=unfold[3:4,5:6]
c=unfold[3:4,1:2]
B=unfold[1:2,5:6]
b=unfold[5:6,5:6]
a=unfold[3:4,3:4]
A=unfold[3:4,7:8]
List=list(A,a,B,b,C,c,unfold)
List
}


#魔方的变换
Transform <- function(Cha) #输入由U/V/F/E/R/K构成的字符串
{
Cha=unlist(strsplit(Cha,split="")) #将字符串的字母逐个拆开
for(i in Cha)
{
if(i=="U"){cube=U(cube)}
if(i=="V"){cube=V(cube)}
if(i=="F"){cube=F(ABup(cube)); cube=BAup(cube)}
if(i=="E"){cube=E(ABup(cube)); cube=BAup(cube)}
if(i=="R"){cube=R(ACup(cube)); cube=CAup(cube)}
if(i=="K"){cube=K(ACup(cube)); cube=CAup(cube)}
draw(cube[[7]])
Sys.sleep(0.2)
}
cube[[7]]
}

Transform(rep("RVE",30))

– END –

 

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 553388607@qq.com 举报,一经查实,本站将立刻删除。 如若转载,请注明出处:https://www.swt6.com/10766.html