通用逻辑问题求解程序

通用逻辑问题求解程序

五一的时候我发现一本逻辑题目的小册子,买过来之后本想做做脑力体操消磨一下时间,可是做了不到3到题我就不耐烦了,闲下来我就想能否写一个程序让计算机去求解这类问题呢,经过整个假期的努力居然做成了,欣喜之余我忍不住就想把它共享出来。

首先我们看一下书里面的第一个题目:

斯科特先生、他的妹妹、他的儿子、他的女儿都是网球选手。关于这四人有以下的情况:

(1) 最佳选手的的孪生同胞与最差选手的性别相同。

(2) 最佳选手与最差选手的年龄相同

请问谁是最佳选手

对于这样的问题,我的第一个困难是如何让计算机理解它,经过分析我设计了一门描述这类问题的语言,只要输入这种语言的文件,计算机就能为你自动搜索出所要的结果。为了让读者对这门语言有一个感性的认识,下面给出描述最佳选手问题的输入:

所有人{} = {"斯科特","妹妹","儿子","女儿"};

性别{} = {"",""}; 年龄{} = {1,2,3,4};

年龄 year(所有人); 性别 sex(所有人);

所有人 同胞(所有人); 所有人 最差,最佳;

sex("斯科特") = ""; sex("妹妹") = ""; sex("儿子") = ""; sex("女儿") = "";

year("斯科特") > year("儿子"); year("斯科特") > year("女儿");

同胞("斯科特")="妹妹";同胞("妹妹")="斯科特";

同胞("儿子")="女儿";同胞("女儿") = "儿子";

最佳 != 最差;

year(最佳) = year(同胞(最佳));  //(1)最佳选手的的孪生同胞

sex(同胞(最佳)) != sex(最差);   //(1)

year(最差) = year(最佳);       //(2)

输出 { "最佳选手是: " 最佳 }

假如上面的文本保存在一个最佳选手.txt”文件中,在得到了我的znlog.exe程序后在控制台下输入”znlog最佳选手.txt”就会产生 最佳选手是: 女儿的输出。

输入语言

要让计算机能够参与求解,首先需要解决的问题就是如何把问题输入进去。经过分析,我认为首先需要设计一门能够描述问题语言。有了描述语言之后求解的过程就是:用户将实际的问题生成一个用这门语言描述的文本文件,然后将文件告诉求解程序,求解程序分析语言,进行搜索,产生输出。

当然完全通用的描述语言远不是我一个人能够设计好的,就算prolog的解析分析程序也不是我能写成的,不过大多数(特别是我手头小册子中的)逻辑问题都不是太复杂,我发现它们可以用几个简单的语言就能描述。

集合定义

通常的逻辑问题一般是求解某些变量的值,而且逻辑问题中变量的可能取值是已经给定的有限多个,例如上面问题中最佳选手的可能取值就只能是:"斯科特","妹妹","儿子","女儿",这样我的语言中就首先需要有集合定义,下面是我对集合定义的语法设计:

集合名{} = {集合元素, 集合元素,……};

集合元素可以是数字或者字符串,但是同一个集合中集合元素不能同时包含数字和字符串。出于实现难度的考虑我限制数字只能是整数,数字集合可以使用[a,b]的语法,[a,b]表示从a开始到b的所有数,例如:

A{} = {[3,7],9,10}; 就等价于 A{} = {3,4,5,6,7,9,10};

在定义字符串集合的时候每个字符串都必须用””号括起来,例如下面是一个字符串集合的例子:

B{} = { “张三”,”李四”,”王五” };

每个集合定义必须占用一个单独的语句,每个语句使用;号作为结束符。

变量定义

说完集合之后就该说到变量了,每个变量在使用前都需要给出它的定义,变量定义语法为:

集合名 变量1, 变量2,……;

在定义变量时第一个需要给出的就是它的类型,也就是已经定义了的集合名字。这个类型规定了变量的取值范围。多个变量可以定义在一个语句中。

为了满足需要,我一共设计了三种变量,一种是单变量,一种是序变量,一种是参变量。

单变量是最简单的,例如语句  A a; 就定义一个单变量a,这个a的取值范围是A

序变量稍微复杂一些,例如语句 B x[]; 就定义一个序变量x。一个序变量相当于n个单变量,n的个数等于类型中元素的个数,例如这里的x就相当于 B x1,x2,x3这三个变量,并且这三个变量的取值互不相同。序变量可以使用[]符号来使用它,例如可以使用x[1],x[2],x[3]语法来使用x[]中的下标从1开始到类型的个数。序变量还可以使用()符号来使用它,例如 x(“张三”)表示张三x中的序号,它相当于一个{1,2,3} x张三的变量。

参变量相当于一个函数,例如语句 A f(B); 就定义了一个参变量,参变量的定义语法为:

变量名(参数1类型,参数2类型,……)

由于时间有限我暂时只支持一个参数的定义方式。也就是说现在的znlog程序只接受语法为:变量名(参数类型); 的定义。

一个参变量相当于n个单变量,n的个数等于参数类型中元素的个数,例如上面的f相当于A f张三,f李四,f王五;这三个变量,参变量中各个单变量的取值可以相同。参变量可以使用f(“张三”)这样的语法来使用它。

条件定义

接下来该说到条件定义了,每个条件使用一个单独的语句;条件语句是一个可以很复杂的表达式。表达式中可以使用 + - * / %这几个代数运算符,可以使用> < >= <= = !=这几个比较运算符号,可以使用 & | ^ ! -> 这几个逻辑运算符号,优先级的排列是

!

* / %

+ -

> >= < <= = !=

& ^

|

->

另外条件中还可以使用 存在 任意 两个量词,它们的语法是

存在 x 属于 集合名, 其他表达式

任意x 属于 集合名, 其他表达式

例如下面是4阶幻方的条件定义:

取值{} = {1,2,3,4}; 编号{} = {[0,15]}; 取值 M(编号);

任意 x 属于 编号, 任意 y 属于 编号, x/4=y/4 | x%4=y%4 -> x=y | M(x)!=M(y);

输出定义

最后该说的就是输出定义了,znlog在进行搜索的时候,如果发现了一个满足所有条件的解,就会将结果输出出来,输出的方式由用户指定,输出定义的语法如下:

输出{ 输出元素, 输出元素, 输出元素,…… };

输出定义由关键字输出引导,然后在{}中给出所有的输出元素,每个输出元素可以是字符串,也可以是表达式,字符串中使用c风格的/n/t导出换行和制表符。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
通用逻辑题目搜索程序。能够解决诸如爱因斯坦难题之类的逻辑题目。 为了能够表达现实的逻辑题目,软件作者设计了一门语言,这门语言一方面很简单,另一方面也具有很强的表达能力。对于一个实际的逻辑问题,用户只需要用这门语言描述一下,就可一交给程序搜索需要的解。同时用户还可以按照自己的需求定义输出的格式。 五一的时候我发现一本逻辑题目的小册子,买过来之后本想做做脑力体操消磨一下时间,可是做了不到3到题我就不耐烦了,闲下来我就想能否写一个程序让计算机去求解这类问题呢,经过整个假期的努力居然做成了,欣喜之余我忍不住就想把它共享出来。 首先我们看一下书里面的第一个题目: 斯科特先生、他的妹妹、他的儿子、他的女儿都是网球选手。关于这四人有以下的情况: (1) 最佳选手的的孪生同胞与最差选手的性别相同。 (2) 最佳选手与最差选手的年龄相同 请问谁是最佳选手 对于这样的问题,我的第一个困难是如何让计算机理解它,经过分析我设计了一门描述这类问题语言,只要输入这种语言的文件,计算机就能为你自动搜索出所要的结果。为了让读者对这门语言有一个感性的认识,下面给出描述最佳选手问题的输入: 所有人{} = {"斯科特","妹妹","儿子","女儿"}; 性别{} = {"男","女"}; 年龄{} = {1,2,3,4}; 年龄 year(所有人); 性别 sex(所有人); 所有人 同胞(所有人); 所有人 最差,最佳; sex("斯科特") = "男"; sex("妹妹") = "女"; sex("儿子") = "男"; sex("女儿") = "女"; year("斯科特") > year("儿子"); year("斯科特") > year("女儿"); 同胞("斯科特")="妹妹";同胞("妹妹")="斯科特"; 同胞("儿子")="女儿";同胞("女儿") = "儿子"; 最佳 != 最差; year(最佳) = year(同胞(最佳)); //(1)最佳选手的的孪生同胞 sex(同胞(最佳)) != sex(最差); //(1) year(最差) = year(最佳); //(2) 输出 { "最佳选手是: " 最佳 } 假如上面的文本保存在一个”最佳选手.txt”文件中,在得到了我的znlog.exe程序后在控制台下输入”znlog最佳选手.txt”就会产生 “最佳选手是: 女儿”的输出。 如果得到了ZnLogWin.exe程序,只需用此程序打开 最佳选手.txt 文件就能在输出窗口产生结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值