使用prolog逻辑语言解决爱因斯坦斑马难题
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/。
目前商业上广泛使用的编程语言多是命令式或函数式的编程语言,这些语言在某些方面具有很高的相似度,比如 python 和 ruby 在很多地方是相通的,学会了一门,再学另一门便能够事半功倍,很多语言都是如此,然而今天要介绍的这门语言,却跟主流编程语言截然不同,它就是prolog——一门逻辑编程语言。
prolog 是 Programming in Logic 的缩写,它被广泛应用在人工智能、自然语言等研究领域,使用它来解决逻辑难题完全不在话下,今天我们将使用它来解决着名的爱因斯坦逻辑难题(斑马难题),首先让我们来认识一下 prolog 的语法。
prolog 基本语法
prolog 中有3种基本元素:事实、规则和查询。事实和规则用于描述数据,查询用于获取问题的答案。
我们可以这样定义事实:
- human(lucy).
- human(lili).
- father(lucy,david).
- sister(lucy,lili).
- sister(lili,lucy).
这段代码表示 lucy 和 lili 是人类,且她们是姐妹,david 是 lucy 的父亲,继续定义规则:
- daughter(Father,A,B) :-
- father(A,Father), sister(A,B)
这段规则表示对于变量A、B,如果Father变量是A的父亲,且A、B是姐妹,则A、B是Father对象的女儿。
注意,在 prolog 中一个词若以小写开头,那么它是一个固定值,若以大写字母开头,则是一个变量。
将这些事实和规则放在一个文件里面,在命令行下打开 prolog ,对这个文件进行编译,即可提出查询,比如 daughter(david,A,_),prolog 将会求出A可能的取值并输出到控制台,最后的下划线是一个占位符,不会进行求值。
在 prolog 中还可以使用递归完成列表和数学等运算,这部分是很强大的,但这里不打算讲,因为有了上面的基础知识后,我们就可以利用它来解决逻辑问题了,下面就让我们来解决“斑马难题”吧。
爱因斯坦逻辑难题
题目:5个不同国家且工作各不相同的人分别住在一条街上的5所房子里,每所房子的颜色不同,每个人都有自己养的不同宠物,喜欢喝不同的饮料。根据以下提示,你能告诉我哪所房子里的人养斑马,哪所房子里的人喜欢喝矿泉水吗?
- 英国人住在红色的房子里
- 西班牙人养了一条狗
- 日本人是一个油漆工
- 意大利人喜欢喝茶
- 挪威人住在左边的第一个房子里
- 绿房子在白房子的右边
- 摄影师养了一只蜗牛
- 外交官住在黄房子里
- 中间那个房子的人喜欢喝牛奶
- 喜欢喝咖啡的人住在绿房子里
- 挪威人住在蓝色的房子旁边
- 小提琴家喜欢喝橘子汁
- 养狐狸的人所住的房子与医生的房子相邻
- 养马的人所住的房子与外交官的房子相邻
这道题的解题关键在于,要以一种清晰的方式将每个房子相关的属性(国家、颜色、工作、宠物、饮料、编号)列出来,前面5个提示中包含了5个国家,那么可以利用这一点画出一个表格,每一行表示一个国家,每一列表示房子的一种属性。一步步根据提示得到一些推论,将结果填入表格,答案便渐渐清晰起来,使用这种人工方式推理的结果如下图所示:
虽然我们知道了解题的关键,但这个问题仍然需要经过很多步的推导才能得出结果,如果使用 prolog 那得到这个问题的答案就简单多了,只需要定义好事实和规则,然后向 prolog 提出问题,逻辑引擎就会为我们查出结果来。
下面是解决这个问题的 prolog 代码。

- house(A,[A,_,_,_,_]).
- house(A,[_,A,_,_,_]).
- house(A,[_,_,A,_,_]).
- house(A,[_,_,_,A,_]).
- house(A,[_,_,_,_,A]).
- right(A,B,[A,B,_,_,_]).
- right(A,B,[_,A,B,_,_]).
- right(A,B,[_,_,A,B,_]).
- right(A,B,[_,_,_,A,B]).
- middle(A,[_,_,A,_,_]).
- first(A,[A,_,_,_,_]).
- neighbor(A,B,[A,B,_,_,_]).
- neighbor(A,B,[_,A,B,_,_]).
- neighbor(A,B,[_,_,A,B,_]).
- neighbor(A,B,[_,_,_,A,B]).
- neighbor(A,B,[B,A,_,_,_]).
- neighbor(A,B,[_,B,A,_,_]).
- neighbor(A,B,[_,_,B,A,_]).
- neighbor(A,B,[_,_,_,B,A]).
- attr(Country,Pet,Color,Drink,Work).
- all_houses(Houses) :-
- house(attr(britsh,_,red,_,_), Houses),
- house(attr(spain,dog,_,_,_), Houses),
- house(attr(japan,_,_,_,painter), Houses),
- house(attr(italy,_,_,tea,_), Houses),
- house(attr(norway,_,_,_,_), Houses),
- first(attr(norway,_,_,_,_), Houses),
- right(attr(_,_,white,_,_), attr(_,_,green,_,_), Houses),
- house(attr(_,snail,_,_,photographer), Houses),
- house(attr(_,_,yellow,_,diplomat), Houses),
- middle(attr(_,_,_,milk,_), Houses),
- house(attr(_,_,green,cafe,_), Houses),
- neighbor(attr(norway,_,_,_,_), attr(_,_,blue,_,_), Houses),
- house(attr(_,_,_,orange,violinst), Houses),
- neighbor(attr(_,fox,_,_,_), attr(_,_,_,_,doctor), Houses),
- neighbor(attr(_,horse,_,_,_), attr(_,_,_,_,diplomat), Houses),
- house(attr(_,zebra,_,_,_), Houses),
- house(attr(_,_,_,water,_), Houses).

在事实部分,将房子看做一个整体,描述了房子在5所房子中、房子的左右关系、中间的房子处于什么位置、第一所房子处于什么位置、房子间的相邻关系以及每所房子拥有哪些属性。
规则部分包含了对题目中提示的描述和最终问题的描述,这些定义是为了告诉逻辑引擎,在求值时必须满足这些条件。
最终的查询为 all_houses(A) ,prolog 逻辑引擎将会查找出满足结果的房子数组,注意每所房子由它的属性组成,这样最后得到的结果为:
[attr(norway, fox, yellow, water, diplomat),
attr(italy, horse, blue, tea, doctor),
attr(britsh, snail, red, milk, photographer),
attr(spain, dog, white, orange, violinst),
attr(japan, zebra, green, cafe, painter)] .
出处:http://www.cnblogs.com/lcomplete/p/3192488.html
使用prolog逻辑语言解决爱因斯坦斑马难题的更多相关文章
- 人工智能技术导论——使用PROLOG逻辑语言解决爱因斯坦斑马文件
一.背景 在上一篇博客https://www.cnblogs.com/wkfvawl/p/12056951.html上,我简单介绍了一下Prolog的一些基本语法,这篇博客主要通过老师课上讲过的一个问 ...
- 七周七语言之使用prolog解决爱因斯坦斑马难题
如果你想获得更好的阅读体验,可以前往我在 github 上的博客进行阅读,http://lcomplete.github.io/blog/2013/06/28/sevenlang-prolog/. 目 ...
- [Go] 使用go语言解决现代编程难题
1.计算机一直在演化,64核,128核等等,但是我们依旧在使用为单核设计的技术编程2.Go语言让分享自己的代码包更容易3.Go语言重新思考传统的面向对象,提供了更高效的复用代码手段4.Go不仅提供高性 ...
- 十年磨一剑,王坚自研的MaxCompute如何解决世界级算力难题
摘要: 2009年这项关于大数据的技术长征开始.王坚带队,目标是自研大数据计算平台MaxCompute统一阿里巴巴内部的数据和大数据计算体系. 大数据时代,随着企业数据规模的急剧增长,传统软件已无法承 ...
- 斑马难题Step by Step
问题描述 分析 代码 在exercism.io被这个 Zebra Puzzle 难住了.这里一步一步的解决... 1.There are five houses. 2.The Englishman l ...
- C语言解决约瑟夫问题详解的代码
将开发过程中比较重要的一些内容做个收藏,下面的内容是关于C语言解决约瑟夫问题详解的内容,希望能对码农有帮助. #pragma once #include<vector> class PRO ...
- 15 GIL 全局解释器锁 C语言解决 top ps
1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...
- indexDB解决过的难题
我第一次使用indexDB是1年前(2018年10月),运用这个黑科技,解决过3个异常棘手的问题(如果不是indexDB 几乎找不到其他解决方案)所以我经常强调,前端一定要学indexDB! 难题一: ...
- 关于C语言解决汉诺塔(hanoi)问题
C语言解决汉诺塔问题 汉诺塔是典型的递归调用问题: hanoi简介:印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔.不论白天黑夜,总有一个僧侣 ...
随机推荐
- Codeforces Round #364 (Div. 1) (差一个后缀自动机)
B. Connecting Universities 大意: 给定树, 给定2*k个点, 求将2*k个点两两匹配, 每个匹配的贡献为两点的距离, 求贡献最大值 单独考虑每条边$(u,v)$的贡献即可, ...
- laravel 异常深度解析
一.前言 做一件事,不仅要知其然,更要知其所以然.大部分的人都生活在别人设计的世界里,不是没有能力去更深一层,更进一步,而是因为自己懒得去思考.也许自己现在要做的就是:不要让自己舒服吧. 二.正题 1 ...
- Mac XMind8 保存时报错
错误提示 截图 日志 查看错误日志的方式:打开xmind –> 关于xmind –> 安装细节 –> 选项卡 “配置” –> 查看错误日志 看到有Caused by: org. ...
- WebSocket教程(二)
运行环境:jdk8 tomcat8 无须其他jar包. package com.reach.socketController; import java.io.IOException; import j ...
- quartz---的Scheduler
quartz---的Scheduler 从这副图中可以很直观的看出来quartz的关系: 调度:Scheduler任务调度器,是实际执行任务调度的控制器.在spring中通过SchedulerFact ...
- curl常用功能
<?php //创建一个新cURL资源 $ch = curl_init(); //******************************************************** ...
- 如何迭代pandas dataframe的行
from:https://blog.csdn.net/tanzuozhev/article/details/76713387 How to iterate over rows in a DataFra ...
- JavaScript学习总结(十八)——JavaScript获取浏览器类型与版本
从网上找到一段使用JavaScript判断浏览器以及浏览器版本的比较好的代码,在此记录一下: 1 <script type="text/javascript"> 2 v ...
- cas HttpServletRequestWrapperFilter
HttpServletRequestWrapperFilter 作用其实很简单就是 在HttpServletRequest对象在包装一次,让其支持getUserPrincipal,getRemoteU ...
- learning uboot bootargs panic parameter
By passing the kernel panic parameter, the system automatically resets after 3 seconds when kernel p ...