关卡前的选择

2020-02-10 04:02:35 中国信息技术教育 2020年1期

陈凯

源起

迷思,是一个很有意思的词语,它的意义,远不止于字面上的“迷惑的思考”,据说它来源于希腊语单词Μ?θο?(mythos),是英语单词Myth的音译,大致是指与现实事物有所对应,能带给人思索,但却未必有答案的神话、传说和虚构的故事。列维-斯特劳斯认为,人们遇到没有办法完全解决的矛盾时,就会编造出一些故事来作为“迷思”。似乎有这样一种感觉,创造这些迷思,其意图不是为那些矛盾找出解决方案,而是为了找出让矛盾继续存在的恰当的理由。

笔者也创造了一个虚构的故事,故事中的主角是一位探索谜之路径的学徒,他在自己的行程中,遇见一处难以通行的关卡,为了打开关卡大门,需要解答一个谜题。但请注意,到现在为止,无论是谜题还是故事本身,它们暂时还不是“迷思”。

谜题是这样的:在关卡的门前摆放着五个大小不一的箱子,必须将它们从小到大摆放整齐,门才会被打开。然而,这不是一个简单的排序问题,因为学徒可做的动作是被严格限定的,他要么可以执行L动作,即交换身边的两个箱子,然后,再和左面的箱子换位,要么执行R动作,将自己右侧的箱子扔到箱子队列的最右面,然后再和自己右侧的箱子(可能已经不是刚才在身边的箱子了)换位。两种动作由图形展示出来,能更容易清楚其中的要求:初始时的状态,如图1所示;执行动作L后,如图2所示;执行动作R后,如图3所示;需要到达的最后目标可能是如图4所示的样子。

最后的结果,只要箱子是从小到大排列就可以了,箱子按要求排列好后,至于学徒可能会在哪个位置,可以没有关系。当然,也可以特别规定学徒所在的位置,这会使得挑战更具难度。大概是因为智商不够,笔者自己在玩这个游戏的时候,没过多久就被搅得七荤八素,对这个明明就是自己想出来的题目叹气。显然,这就是人工智能应该登场的时候了。

解答

在早期的人工智能研究中,比较容易的突破点,就是各种与逻辑推理有关的智力游戏。针对上述任务,可以将各个箱子分别编码为数字1、2、3、4、5,将人编码为数字-1,然后存入列表。无论是L动作还是R动作,都可以很容易地用列表操作来完成。由于每次动作非L即R,所以只要在执行L或R动作之后,记录下箱子和人位置的状态,然后再以此状态为基础,继续执行L或R状态,可以看出,每个状态通往新的状态时,都面临着一个有着两条路径的分叉。当某个状态的箱子的摆放符合要求时,则可宣告解锁完成。比起纯粹随机乱走,借助二叉树来对左右两个动作逐项展开比对,就不会遗漏最快的解答方法。

但要让计算机完成任务,需要涉及不同的技能,以Python解答这个搬箱解锁的谜题的过程为例,在数据匹配环节中需要用到二叉树,而为了使用二叉树,就不得不涉及更多不同的知识技能,它们之间的关系大致如图5所示。

这张图大致展现出:如果要借助二叉树来解决搬箱解锁的谜题,那么还需要很多其他知识技能的支撑,将这些支撑关系用概念图绘制出来,可能呈现出树状结构,甚至更复杂一些,呈现出网状结构,任何一个节点的缺失,都会使得任务无法达成。下面,分别对搬箱解锁谜题解答过程中的几段重要的Python代码进行说明。

1.二叉树的建立和使用

建立二叉树的用途,是为了不遗漏所有的动作路径,如图6所示。

建立二叉树的代码如下页图7所示。

代码中使用到了“anytree”库,利用这个已封装好的树结构对象,可以轻松地建立起二叉树(也可以从底层开始自行建立二叉树对象),由于事先不可能知道二叉树究竟可能有多深,所以无法预先给树的每个节点命名,这里就用到了动态命名的方法:

names['x%s' % int((i-1)/2)].name.copy()

这句语句不仅实现了动态的树节点命名,同时还通过取整函数,将左右两个子节点指定给上一层的某一个父节点。

2.执行L动作和R动作

代码中的doleft函数,作用就是执行L动作,其中涉及的都是列表操作,另外doright函数执行的是R动作,同样是列表操作,如下页图8所示。

3.执行检验动作

检验函数的代码很简单,就是将“人”从列表中去除,然后看剩下的箱子排列是不是“12345”即可,如下页图9所示。

程序运行后很快就可以获得解谜的答案,如下页图10所示。

同时,程序还将二叉树列出,限于篇幅,这里只列出树的一部分,如下页图11所示。

程序代码有四十多行,并且还完全没有考虑解题时效率上可做的优化,与许多迷题解答类的程序相比,已经算是足够简单了。本文中要讨论的问题,不限于程序代码及谜题解答本身。

迷思

假设学徒A和B受困于关卡之前,他们发现自己的解谜能力有限,这时,解谜大师X和Y出现了。

学徒A遇见了大师X,大师X告诉A,有许多解谜大师曾经针对不同的谜语,制造过不同的解谜法宝,自己身边恰巧就带着一个这样的法宝,他称之为搬箱解锁函数,只要学习了函数的使用方法,便能成功解锁,虽然稍微有些麻烦,但学徒A还是很快掌握了法宝的使用方法,他解锁成功后,通过了关卡。

学徒B遇见了大师Y,大师Y的口袋里当然有着各种法宝,包括那个叫做搬箱解锁函数的法宝,但它却要求学徒自己动手,亲手把那个法宝给锻造出来。当然,这很花费时间,因为锻造法宝的工具并不齐备,学徒需要探索通向当前大道的多条小路,去寻找到所有制造法宝的工具。问题是,工具的拥有者可能宣称,某个工具的制作过程本身也是一个谜题——可怜的学徒于是又要去试着解开新的谜语。

学徒A和学徒B,哪一个是幸运的?正如前文所说,迷思本身没有标准答案,或许即将出场的学生C才是最幸运的,因为他先后遇见了大师X和大师Y,也许他还遇见了大师Z,这位大师甚至没有急着让学徒自己打造神奇法宝,却先是笃定地聊起那些谜题创造大师们的奇怪想法的来龙去脉,他又花了不少时间,讲述那些工具锻造师傅的手艺是怎样练成的。

但若是存在以下两个条件,学徒C的幸运就变成了困惑:第一,假设解开谜题通过关卡这件事本身,并不是学徒的最终任务,这一次通关仅仅是一种训练,他的真正目标,是将来能够自主通过各种有着奇怪谜题的关卡;第二,他和导师相处的时间是受到限制的。那么,这三位导师应该怎样安排好和学徒C的每一次见面呢?

笔者创作这个迷思,其实就是为了映射当前基础教育阶段中人工智能教学的困难:面对某个具体的人工智能问题,如果是直接给予学习者一个封装好的函数,那么学习者是无法体会到人工智能的具体实现过程的;但若是要讲述清楚达成某个人工智能任务的各种细节,却又受到学习者当前知识技能水平和教学时间的限制。

既然给出了迷思,笔者自己也努力尝试着给出一种回答:大师X展现出了神奇法宝,他谜一般地通过关卡后消失了,比起關卡自身的谜题,大师X神奇法宝的由来和制造方法,则已经成了更加需要解答的谜题。大师X的行为无疑引来大师Z的一番引经据典的评述,对于大师Z云里雾里一样的高深言论,学徒并不能一下子听明白,这时候大师Y出场了,他找来了用以制造法宝的零件和工具,然后,他带领着学徒,一起经历了用这些零件和工具锻造出神奇法宝过程中重要的一步或者几步,有了实际的经验,大师Z的言语或许就不那么难懂了。

虽然大师们的时间很有限,但他们不会忘记还存在着许多缺失的工具和零件,他们画出了一幅用以进一步探索的解谜地图。最后,他们还会嘱咐道:其实,还有许多道路没有被开拓出来,毕竟,路是人走出来的。

广东快乐十分