Learn Prolog Now 翻译 - 第三章 - 递归 - 第四节,更多的实践和练习

时间:2021-09-05 20:13:09

 在学习了前三章内容后,我们应该对Prolog编程有了直观和理性的认识。由于合一、变量初始化、证明搜索和递归都是Prolog的核心概念,所以有如下更多的一些实践和练习。

这里我会先录入题目,后期再给出我自己的程序代码和一些思考。

 

实践1

 试想有如下的描述迷宫的知识库。其中的事实描述了点和点之间的联通关系,即connected/2谓词逻辑给出了这样的事实:迷宫中能从参数1的点,直接到达参数2的点。而且,

联通关系是有方向的、单向不能往返的:

connected(1,2). 
   connected(3,4). 
   connected(5,6). 
   connected(7,8). 
   connected(9,10). 
   connected(12,13). 
   connected(13,14). 
   connected(15,16). 
   connected(17,18). 
   connected(19,20). 
   connected(4,1). 
   connected(6,3). 
   connected(4,7). 
   connected(6,11). 
   connected(14,9). 
   connected(11,15). 
   connected(16,12). 
   connected(14,17). 
   connected(16,19).

 请写出一个谓词逻辑path/2,给出迷宫中哪些点是能够联通(直接或者间接)的。比如,点5是否能够达到点10?当起点是1时,能够到达哪些点?

 

实践2

 有如下的交通信息知识库:

byCar(auckland, hamilton).
byCar(hamilton, raglan).
byCar(valmont, saarbruecken).
byCar(valmont, metz).

byTrain(metz, frankfurt).
byTrain(saarbruecken, frankfurt).
byTrain(metz, paris).
byTrain(saarbruecken, paris).

byPlane(frankfurt, bangkok).
byPlane(frankfurt, singapore).
byPlane(paris, losAngeles).
byPlane(bangkok, auckland).
byPlane(singapore, auckland).
byPlane(losAngeles, auckland).

 请写出一个谓词逻辑travel/2,可以描述从一个地点到达另外一个地点(间接或者直接),可以通过car、train和plane进行换乘。比如,如果查询:

 ?- travel(valmont, raglan).

 Prolog会回答true。

 

实践3

 所以,通过实践2中的谓词逻辑travel/2,可以知道Valmont可以达到Raglan。这很有用,但是当你计划一段旅行的时候,你希望更确切的一些信息,比如其中详细的路途是

怎么样的。请写一个谓词逻辑travel/3,可以告诉具体的路径,比如,如果查询:

 ?- travel(valmont, losAngeles, X).

 X = go(valmont, metz, go(metz, paris, go(paris, losAngeles)))

 

实践4

 扩展实践3中的谓词逻辑travel/3,使其不仅能够给出从一个地方到另一个地方的路由,并且能够给出如何到达的方式。即,新的程序可以让我们知道,在旅行的每一段,是

使用的car,train还是plane作为交通工作的。

 

实践5

 写出一个3元谓词combine1/3,将头两个参数的列表,合并为第三个参数的列表,例如:

   ?- combine1([a, b, c], [1, 2, 3], X).

   X = [a, 1, b, 2, c, 3]

   ?- combine2([f, b, yip, yup], [glu, gla, gli, glo], Result).

   X = [f, glu, b, gla, yip, gli, yup, glo]

 

 写出一个3元谓词combine2/3,将头两个参数的列表,合并为第三个参数的列表,例如:

   ?- combine2([a, b, c], [1, 2, 3], X).

   X = [[a, 1], [b, 2], [c, 3]]

   ?- combine2([f, b, yip, yup], [glu, gla, gli, glo], Result).

   X = [[f, glu], [b, gla], [yip, gli], [yup, glo]]

 

 写一个3元谓词combine3/3,将头两个参数的列表,合并为第三个参数的列表,例如:

   ?- combine3([a, b, c], [1, 2, 3], X).

   X = [j(a,1), j(b,2), j(c,3)]

   ?- combine3([f, b, yip, yup], [glu, gla, gli, glo]).

   X = [j(f, glu), j(b, gla), j(yip, gli), j(yup, glo)]

    

 今后的学习中,我会找更多的一些实践题目,包括著名的数独问题,四色地图问题,八皇后问题,汉诺塔问题等等,一一分析。关于这章实践的答案,会陆续附上。

 

我的答案和解释:

 

 实践1的path/2定义如下:

   path(X, Y) :- connected(X, Y).

   path(X, Y) :- connected(X, Z), path(Z, Y).

 思路:首先考虑直接连通的情况,作为基础子句;然后考虑递归:设置一个中间变量Z,X和Z直接连通,然后Z和Y递归调用Path。