逻辑思维的Prolog
起因
从小就喜欢玩些智力游戏,也经常问别人一些考验智商的小问题。但自从开始程序猿这条不归路,我越来越发现无法与其他人交流。说的东西他们不懂,而且他们也不屑懂。现在写的这些个程序,确实都不需要多少思考,鉴定程序好坏的标准居然只成了是否报错,是否考虑的很周全。
前阵子看到prolog,惊讶除了函数式编程以外,还有如此令我思想为之一开的语言。逻辑式编程确实符合人类思维,也确实让我对递归、回溯等有另一种认识。
突然想给大家出个题,只是这次题与程序有关。
Prolog基础
即是逻辑语言,程序思维在此没有多大帮助,所以会不会程序都没问题。即使是程序猿,如我这等程序猿接触此语言的相信也不是很多。
普及知识
那么先普及一下知识。
有兴趣的完全可以不看我写的,自己去百度谷歌。
在此用一个图来解释。
本来弄了好多人,打了不少关系,最后想想算了。关系还是别太复杂了。
比如说是徐长卿和紫萱生下林清儿(其实不是),然后巫王和林清儿生赵灵儿,赵灵儿和李逍遥生林忆如,旁边那个王小虎是陪衬品。
现在已知林忆如的妈妈是赵灵儿,赵灵儿的妈妈是林清儿,林清儿的妈妈是紫萱,那么用prolog就可以这样描述:
妈妈(紫萱,林清儿).
妈妈(林清儿,赵灵儿).
妈妈(赵灵儿,林忆如).
注意每行后面有个点。
然后告诉prolog奶奶的意思就是妈妈的妈妈,语句可以这样写:
奶奶(X,Y) :- 妈妈(X,Z),妈妈(Z,Y).
注意 :- 是一个冒号一个减号。
这时候,你如果问prolog赵灵儿的奶奶是谁:
奶奶(X,赵灵儿).
那么prolog会输出:
X = 紫萱
注意:假设这是一个【母系氏族】。
如果你觉得简单,那么希望你一直这样觉得。
几点注意
代码里面的每一行都代表一个子句(clause)。其中带有(:-
)的子句叫做规则(rule),不带(:-
)的子句叫做事实(fact)。
- 注意1:这里是为了阅读方便才使用汉字的,真正的prolog是不允许使用除了基本字符以外字符的,也就是说,上面的句子必须写成
mama(zixuan,lingqinger).
电脑才能够真正的理解。 - 注意2:最末尾的“.”一定不能掉,它表示一个句子结束。
- 注意3:上面词汇对于电脑来说并没有真正的含义,所以我们完全可以用 mama(zx,lqe).来表达这个关系,更进一步,我们甚至可以用mm(a,b).来表达,只要你自己心里清楚mm表示妈妈,a表示紫萱,b表示林清儿就可以了。
- 注意4:
妈妈(紫萱,林清儿).
这里紫萱和林清儿没有所谓的先后顺序,你完全可以写成妈妈(林清儿,紫萱).只要后面所有的【妈妈】这个事实都是后面的是前面的妈妈就可以了。比如说妈妈(林清儿,赵灵儿).则应改为妈妈(赵灵儿,林清儿).
另外,在Prolog里面诸如“zixuan”和“lingqinger”这类以小写英文字母开头的名称我们称它们为原子(atom),以大写英文字母为开头的名称我们称它们为变量,例如上面程序里面的“X”和“Y”。顾名思义,原子是常量,即它的值是不可变的,而变量的值可以改变。最后需要讲的是,在Prolog里面“,”代表逻辑关系中的“且”,“;”代表逻辑关系里面的“或”。
运行代码
那么,你现在可以编写代码去运行看看效果了。
首先要有prolog的环境。
SWI-Prolog中找到适合自己机器的版本。下载、安装、运行。
在文本文件中输入以上代码:
mama(zixuan,linqinger).
mama(linqinger,zhaolinger).
mama(zhaolinger,linyiru).
nainai(X,Y) :- mama(X,Z),mama(Z,Y).
然后保存成pl扩展名,例如文件存在d:/xianjian.pl。最后进入SWI-Prolog,输入
consult('d:/xianjian.pl').
如果成功则输出Yes
,不确保你使用其他系统或版本输出True
这时候你问prolog:
nainai(X,zhaolinger).
那么他会给你说
X = zixuan
你问:
nainai(linqinger,linyiru).
得到结果是真
问:
nainai(zhaolinger,linyiru).
则返回是假
继续逻辑
下来多点代码:
nan(xuchangqing).
nan(wuwang).
nan(lixiaoyao).
nan(wangxiaohu).
nv(zixuan).
nv(linqinger).
nv(zhaolinger).
nv(linyiru).
baba(xuchangqing,linqinger).
baba(wuwang,zhaolinger).
baba(lixiaoyao,linyiru).
mama(zixuan,linqinger).
mama(linqinger,zhaolinger).
mama(zhaolinger,linyiru).
那么nver这个规则怎么定义?
这个就不浪费世间了,直接告诉答案:
nver(X,Y):-baba(Y,X);mama(Y,X),nv(X).
扯点程序
看到这里,你可能觉得程序不过如此。
这让我等程序猿如何是好。
所以我提出如下需求,写下如下代码。
已知:
mama(zixuan,linqinger).
mama(linqinger,zhaolinger).
mama(zhaolinger,linyiru).
需求:
定义一个女娲氏族规则。说简单一点,定义一个祖先的规则。当我问zuxian(X,linyiru).
Prolog会告诉我
X=zhaolinger ;
X=linqinger ;
X=zixuan ;
好吧,这个问题也给答案
zuxian(X,Y):-mama(X,Y).
zuxian(X,Y):-mama(X,Z),zuxian(Z,Y).
也可以直接写成:
zuxian(X,Y):-mama(X,Y);mama(X,Z),zuxian(Z,Y).
这里我想说一句,人理解迭代,神理解递归。
最后一题
在上面表格中白色的方格(带有LXX标识的方格)里面填上英文单词,可供选择的单词有:
word(d,o,g). word(r,u,n). word(t,o,p). word(f,i,v,e).
word(f,o,u,r). word(l,o,s,t). word(m,e,s,s). word(u,n,i,t).
word(b,a,k,e,r). word(f,o,r,u,m). word(g,r,e,e,n).
word(s,u,p,e,r). word(p,r,o,l,o,g). word(v,a,n,i,s,h).
word(w,o,n,d,e,r). word(y,e,l,l,o,w).
那么开始吧。
备注
最后,本文内容其中有出处,由于猜谜原因,没有给出出处,估计也没几个人猜,等自己过了这个劲头再给出处。
出题的人,很大程序上都是想让解题的人觉得很难,使用各种巧妙的技巧,费了好大的劲终于解出来了,然后以此证明自己之伟大。
如果那些程序猿觉得非工作时间写与工作、前途无关的程序是一件愚蠢的事情,那么,我也不再多说什么。
blog comments powered by Disqus