重拾三阶魔方

前天玩了一次别人的三阶魔方,5分钟内都没能复原。

岁月不饶人,说的也不是没有道理。

想当年我也曾凭借一个简化版的CFOP公式,在1分钟内就能把三阶魔方复原。(当时的世界纪录是6.x秒。我当然差的还远,即便要自称“高手”,也必须是30秒以内复原才算;但是在同龄人之间自然可以炫耀一番。)5~6年的时间,竟然已经几乎忘光了。

想想也可笑。“想当年”,我们不也是猛练各种解题技巧,在100分钟内把一张数学卷子给做完?5~6年以后,就算不设时间限制,恐怕有些题也是没法做出来。这么说起来,当初又为什么要训练到那样的程度呢?

不过魔方确实是一个很有意思的玩具。就算我练不成速拧高手(现在的世界纪录大概是5.x秒,时代在进步),没事玩玩也是挺有意思的。所以产生了重拾三阶魔方的念头。

我买了一只型号叫作GAN357的魔方,它附送了一份公式参考,包括入门级别的层先法和比较高级的CFOP法。层先法总共10个公式,比较适合入门。对于拼底块十字这种最最基础的没有公式可言的操作,参考上也做了详细的解释。所以,仅靠这张参考就完全学会魔方复原,一点也不困难。CFOP法是层先法的改进,提高了复原的速度,但是相应地,公式也就大大增加,多达119个公式。要熟练掌握CFOP是不那么容易的,但是一旦熟练,复原魔方的时间就可以缩短到30秒乃至更短。

应该说,现在玩魔方比我当年要轻松多了,魔方买到手攻略也就送到家,还有“玩”的必要吗?直接就是入门到进阶一条龙服务,把菜鸟培养成高手。

我当年玩魔方的时候哪有攻略可查。可惜,凭借自己的智慧没能复原整个魔方。最好的成绩是复原了前两层,而对于第三层根本束手无策(其实是不舍得破坏前两层已经拼好的所谓“完美”状态)。

出于想要复原魔方的强烈愿望,还是忍不住去网上查找复原魔方有没有什么窍门。然后就接触到了所谓的层先法解法和公式记号。对于公式,心里只能用“神奇”来评价;它就像巫师的咒语一样,念一遍就会起效果。按部就班地操作,最后果不其然复原了整个魔方的全部六面。当时的心情,我想每个玩过魔方的人都有切身体验吧。

我曾把复原魔方的公式记在了一本笔记本上。那本笔记本后来在一次清理房间的过程中被意外地和废纸一起卖掉了,就再也找不到了。

但我想,要不是一开始有过自己的动手和研究,而是上来就套公式的话,复原一个魔方就应该是意料之中的理所当然的事情,恐怕不会有太多的新鲜感和成就感。如果一定要类比的话,应试教育就是那种一上来就把所有招式都教给你,解题只需套公式而无需深入研究和理解,入门到进阶的一条龙服务,把门外汉直接培养成解题能手。如果一个人志在获得魔方速拧的世界冠军,那么我觉得“一条龙服务”不失为一种实际的选择。但这同时意味着失去了所有的乐趣和成就。死记硬背+苦练不说,所有的成就都也不过是前人的成果,我做得再好,只能说明我和前人一样好,否则就是我连前人也不如。

并非每个人生下来都有想取得速拧冠军的理想。真正有这样理想的人,一般来说,一定是玩了很长时间的魔方,对它有很深的兴趣的人。在此基础之上,他才愿意去记忆大量的公式并且训练手速。对玩魔方不感兴趣的人,或者天生手笨的人,即便有“一条龙服务”摆在面前,也不见得会动心。不幸的是,每个人生下来就被寄予考上好学校的期望,因而注定着要参与各种各样的招生考试。选择应试教育其实只是这样的大背景下一种必然的结果而已。

扯远了。我不否认间接经验的价值。事实上,因为间接经验的存在人类的知识才能迅速地发展。虽然原创研究是推动人类进步的重要因素,但现实中大多数人最常用的知识,其实都是很久以前传下来的间接经验(加减乘除?)。有的人手快,有的人脑子好。脑子好的人想出了速拧的公式,但他未必能创造世界纪录。手快的人可能没法自己推导出魔方的复原公式,但是他通过理解他人总结的公式,发挥自己手快的特长,就能创造世界纪录。闻道有先后,术业有专攻,如是而已。

正因为公式的存在,魔方才可能成为大众的玩具。复原三阶魔方其实是一种在外行人看来非常了不起,但其实很容易的本事。不少人学复原魔方的初衷只是为了炫耀。炫耀炫耀也就罢了,不宜以此宣称自己天资聪颖,最多也只是熟能生巧罢了。

刚才试了试,似乎仍然需要1分多钟的时间才能复原。这样的成绩似乎还差得很远,不过我并不在意。自己玩得开心就好。

今天我另外还看了三阶魔方的其他解法(不是基于层先法),看的时候甚感吃力。感觉层先法在我脑中已形成固定模式无法改变。这大概也是很多其他领域中会出现的事情:一旦对某种理论高度熟悉,就会形成固定的看法,而所有其他的理论都会被看作荒诞之谈。

继续阅读 →

用gnuplot将数据可视化

今天我做了两件事,其一是了解了样条插值的概念,其二是观察了使用有限差分方法求解的调和场。做这两件事都用到了gnuplot。

Gnuplot是一个可用于作图的免费软件。使用它可以将数值计算的结果以图像的方式呈现,以获得直观的感受。

观察插值函数

试想原本有一个连续函数,由于测量的原因现在只知道其中的个别点的位置。

但是我想知道中间某个点处的函数值,我会这么做:用一条光滑的曲线把这些点连接起来,然后根据图像来找到对应的函数值。这就是科学实验中常用的图解法的原理。

继续阅读 →

判定给定边长可否构成三角形的一个定理

本定理来自一道算法竞赛题:

给定任意多条边,每条边都是不超过1,000,000,000的正整数。请给出一个算法,判断其中是否存在3条边可以构成三角形。

应用该定理可以有效地解决此问题。

定理

给定n个边长,如果其中最大的边长与最小的边长的比值小于第n个斐波那契数,那么其中必存在3个边长可以构成三角形。

应用

由题中条件可知,最大的边长和最短的边长的比值不超过\(1,000,000,000 < F_{45}\)。所以,只要边的个数达到45,根据上述定理,就必然存在3条边可以构成三角形。如果边的个数少于45个,也很好办,穷举解决即可(\({45 \choose 3} = 14190\),穷举量很小)。

继续阅读 →

减小Lua的二进制体积

Lua本身已经是一个十分轻量级的脚本语言。在我的64位Windows上编译出来的lua53.dll仅248K。(参照物:python34.dll为3963K。)

Lua Technical Note 1介绍了通过删减功能来进一步减小Lua的二进制体积的方法。这篇文章针对的是Lua 3.2,16年前的版本,尽管如此,它仍然给了我很大的启发。

首先看Lua 5.3中哪些模块占用的二进制体积最多:

size	%all	%core	file
23571	7%	12%	lauxlib.o
20909	6%	11%	lparser.o
20256	6%	11%	lapi.o
18403	5%	10%	lvm.o
14413	4%	8%	llex.o
13526	4%	7%	lcode.o
12584	4%	7%	lgc.o
10214	3%	5%	ldebug.o
8967	3%	5%	lobject.o
8776	2%	5%	ldo.o
7002	2%	4%	ltable.o
5087	1%	3%	lundump.o
4887	1%	3%	lstate.o
3970	1%	2%	ltm.o
3832	1%	2%	ldump.o
2818	1%	1%	lstring.o
2525	1%	1%	lfunc.o
2170	1%	1%	linit.o
1810	1%	1%	lopcodes.o
1498	0%	1%	lmem.o
1406	0%	1%	lzio.o
860	0%	0%	lctype.o
189484	54%	100%	(core)
继续阅读 →

Lua语言中的“惊喜”

Lua在有些地方没有采用其他语言(尤其是C)的约定俗成,所以经常给程序编写者带来惊喜(surprise, “gotcha”)。根据我的经验,整理如下:

  1. 不等号是~=,而不是!=
  • 这是我写Lua程序时最常犯的一个笔误。只能说,几乎所有的程序语言,不等号用的都是!=(C家族),还有一部分用<>(Pascal, Basic, SQL)。用~=真的只有Lua一家。
继续阅读 →

在位图上画直线

在显示器上画出的各种图形中,直线是最简单的一种。这里说的直线,有确定的起点和终点;数学家也许更愿意称其为线段

画直线是如此的简单,以至于人们也许已经忽略了它也是逐个像素点绘制出来的,而把它当作一种原子的操作。我也是如此认为,直到昨天一位同学谈他的计算机图形学课程时,说到了这个问题。

于是我尝试用自己的知识来解决这个问题。显示器上的直线和数学上的线段最明显的差别是,前者是由有限个点构成的,而后者不是。所以,显示器上的直线只是一种近似,而我要使得这种近似的效果尽量好。

为了简化问题,假设显示器显示的是一幅单色的位图。我想到的做法是这样的:

  1. 画起点。
  2. 画完一个点后,在其周围的点中,找到距离给定直线最近的点,然后画这个点。
  3. 重复第2步,直到画了终点为止。

这个做法看上去应该没有问题,只有一些细节部分需要考虑。

继续阅读 →

发现了MinGW GCC的一个bug

我今天发现MinGW内置的打印函数__mingw_printf在处理%a格式的时候会产生不正确的输出。下面这段程序体现了这个问题。

#include <stdio.h>
#include <stdarg.h>

int main()
{
	printf("%a %a\n", 1.0, 1.1);
	__mingw_printf("%a %a\n", 1.0, 1.1);
	return 0;
}

输出是

0x1.000000p+0 0x1.19999ap+0
0x0p-63 0x8.cccccccccccdp-3

因为浮点数1.0显然不能表示为0x0p-63,所以__mingw_printf是错的。

这个错误我提交在 http://sourceforge.net/p/mingw-w64/bugs/459/ ,过几天我看看有没有人回应。

继续阅读 →

连连看游戏中的配对路径搜索

在连连看游戏中,两个图案可以消去的条件是:

  1. 两者图案相同。
  2. 两种直接存在一条通路,它是一条只经过没有图案的地方、且转折点不超过2个的折线。满足此条件的两个图案被称为是可相连的。

要判断条件1非常容易,所以主要考虑怎样判断条件2。举一个具体的例子如下,图中空格表示没有图案的地方,字母和#表示图案,-+|表示路径。

          
 ### ##A# 
 # ### |# 
 +-----+# 
 A####### 
          

在这个例子中,A和A是可相连的。图中所给出的路径含有两个转折点。

对于此类问题,能否给出一个普遍的判断方法?在实际问题中(例如在连连看游戏里),如果判定两个图案是可相连的,还要指出一条具体的路径。

继续阅读 →

物理老师的信

今天是大学物理课期末考试的日子。大约是昨天,物理老师在他和学生的邮箱里发了一封邮件,内容主要是回应网络上出现的针对他的,以及针对物理教学的一些错误言论。有些内容看起来真是可笑而可悲。

他讲的课,钻研和探究的成分要多一些。有的时候也会偏离主题,谈到他的人生经历和感悟上面去——同学们称之为“扯淡”。由于过多的钻研和“扯淡”,我们班的课程比其他班慢了许多。有的同学不满意,在网上开帖子骂他。

理想的情况是老师和学生应当保持一种平等的关系——在网上攻击老师,显然不是这种关系的体现。但是现状是,考试是第一位的,对于班里众多的优秀学生而言尤其如此。在他们看来,好的老师应该做的,就是尽他所能让学生考出高的分数。选择自己的教学模式本应是教师的基本权利,现在却因为必须迎合学生的需求,变成了mission impossible。这难道不算是大学教育乃至整个教育体制的一种悲哀?

继续阅读 →

定居GitHub.io

我需要一个可靠的地方存放我的文字。曾经试过很多办法,无论是纸质的、电子的或是基于网络的形式,都感觉不太靠谱:

  • 纸质的记事本,某一天弄丢了,就找不回来了。
  • 在本机记录的文本,不方便保存历史记录,在更换电脑的时候有可能忘记迁移数据。
  • 基于网络的内容管理系统,服务的稳定性是一个很大的问题,当我需要从一个平台迁移到另一个平台的时候,导入/导出也是一个艰巨的工作。

现在我用Git来管理我这些文字,并且上传到GitHub服务器中。利用GitHub.io提供的Web服务进行展示。我认为有如下的好处。

继续阅读 →