给定知识库的Prolog难题 - 不工作

时间:2017-05-29 09:52:24

标签: prolog zebra-puzzle

我知道这个主题的标题存在于此:A prolog program that reflects people sitting at a round table

但我需要一个不同的解决方案,更简单。

所以我有这个问题,四个人坐在一张方桌旁。

我们知道他们的名字。 那个人是骨科医生,有人是牙医,有人是外科医生,有人是儿科医生。

我们有一个您将在代码中看到的知识库。

我们必须找到儿科医生的名字。

我的程序找到了它,但没有打印代表桌子上座位的列表的所有四种可能组合。

table(List):-
    length(List,4),
    member(convive(argiro,_,female),List),
    member(convive(georgia,_,female),List),
    member(convive(basilis,_,male),List),
    member(convive(dimitris,_,male),List),
    left(convive(_,dentist,_),convive(argiro,_,female),List),
    oppo(convive(_,surgeon,_),convive(basilis,_,male),List),
    next(convive(georgia,_,female),convive(dimitris,_,male),List),
    left(convive(_,_,female),convive(_,orthopedist,_),List),
    member(convive(_,pediatrecian,_),List).

left(X,Y,ConLs):-append(_,[X,Y|_],ConLs).

left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).

next(X,Y,ConLs):-left(X,Y,ConLs).

next(X,Y,ConLs):-append(_,[Y,X|_],ConLs).

next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).

oppo(X,Y,ConLs):-next(X,Z,ConLs),next(Z,Y,ConLs),X\==Y.

在终端上我得到:

  

? - table(List),member(convive(Name,pediatrecian,_),List)。

     

List = [convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeiat,female),convive(dimitris,orthopedist,male)],   姓名= argiro;

     

List = [recive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],   姓名= argiro;

     

假。

正如您所看到的,我得到了名字,但只有两个可能的列表代表每个人的就座位置。还应该有:

  

List = [recive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeon,female)]

     

List = [convive(argiro,pediatrecian,female),convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male)]

我使用了

left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).

next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).

但是,他们没有做任何事情,如果我删除它们,我会得到相同的结果。

更新

table(List):-
length(List,4),
member(convive(argiro,_,female),List),
member(convive(georgia,_,female),List),
member(convive(basilis,_,male),List),
member(convive(dimitris,_,male),List),
left(convive(_,dentist,_),convive(argiro,_,female),List),
oppo(convive(_,surgeon,_),convive(basilis,_,male),List),
next(convive(georgia,_,female),convive(dimitris,_,male),List),
left(convive(_,_,female),convive(_,orthopedist,_),List),
member(convive(_,pediatrecian,_),List).

left(X,Y,ConLs):-append(_,[X,Y|_],ConLs).

left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).

next(X,Y,ConLs):-left(X,Y,ConLs);left(Y,X,ConLs).

%next(X,Y,ConLs):-append(_,[Y,X|_],ConLs).

next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).

%oppo(X,Y,ConLs):-next(X,Z,ConLs),next(Z,Y,ConLs),X\==Y.

oppo(X,Y,[X,_,Y,_]).

oppo(X,Y,[Y,_,X,_]).

oppo(X,Y,[_,X,_,Y]).

oppo(X,Y,[_,Y,_,X]).

所以,oppo / 3似乎在给定的列表上运行良好

  

? - table(List), oppo (convive(argiro,pediatrecian,female),姓名,名单)。

     

List = [convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeiat,female),convive(dimitris,orthopedist,male)],

     

姓名=复活(dimitris,骨科医生,男性);

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名=复活(dimitris,骨科医生,男性);

     

假。

左/ 3似乎是在做我想要解决的事情,它在argiro排名第2,格鲁吉亚是3这是一个简单的案例,但是在第二个列表中你可以看到上面的oppo / 3结果,其中argiro是4号而格鲁吉亚是1号,它应该看到格鲁吉亚再次位于argiro的左边但是没有。

  

? - table(List), left (convive(argiro,pediatrecian,female),姓名,名单)。

     

List = [convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeiat,female),convive(dimitris,orthopedist,male)],

     

姓名=复活(格鲁吉亚,外科医生,女性);

     

假。

现在下一个/ 3会返回一些非常令人不安的结果。我不知道该怎么做,我是Prolog的新手。有些是好的,但有些人似乎将整个数组作为结果,有些人说List = Name。

前三个结果没问题,第四个结果与左/ 3相同,它无法看到列表中的第一个与最后一个相邻,所以它返回一个空阵列

这里发生了什么?

  

? - table(List), next (convive(argiro,pediatrecian,female),姓名,名单)。

     

List = [convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeiat,female),convive(dimitris,orthopedist,male)],

     

姓名=复活(格鲁吉亚,外科医生,女性);

     

List = [convive(basilis,dentist,male),convive(argiro,pediatrecian,female),convive(georgia,surgeiat,female),convive(dimitris,orthopedist,male)],

     

姓名=复活(罗勒,牙医,男性);

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名=复活(罗勒,牙医,男性);

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

名称= [];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [convive(格鲁吉亚,外科医生,女性)];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [复活(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性)];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [驯养(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性),痴迷(罗勒,牙医,男性)];

     

列表=姓名,

     

姓名= [驯养(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性),痴迷(罗勒,牙医,男性),痴迷(argiro,pediatrecian,女性)];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

名称= [];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [convive(格鲁吉亚,外科医生,女性)];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [复活(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性)];

     

List = [convive(georgia,surgeon,female),convive(dimitris,orthopedist,male),convive(basilis,dentist,male),convive(argiro,pediatrecian,female)],

     

姓名= [驯养(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性),痴迷(罗勒,牙医,男性)];

     

列表=姓名,

     

姓名= [驯养(格鲁吉亚,外科医生,女性),痴迷(dimitris,骨科医生,男性),痴迷(罗勒,牙医,男性),痴迷(argiro,pediatrecian,女性)];

     

假。

更新

所以我知道前缀/ 2适用于字符串,例如, prefix(x,[x,y,z]).返回false。 这就是为什么它不起作用,这解释了下一个/ 3的结果,但我的问题仍然没有解决。

使用左侧和下一个方法处理列表的第一个和最后一个部分的任何其他方法?

1 个答案:

答案 0 :(得分:0)

我敢打赌\==中的罪魁祸首是oppo,因为这些谓词在这里以生成方式使用。试着摆脱它。只需手动编码这四种可能性就足够了 - 毕竟你的清单是固定的,非常短的:

oppo(X,Y,[X,_,Y,_]).
.....
如果编码为next/3两次调用的分离,则

left/3更容易/更清晰。

对于left/3本身,您也可以通过<{1}}

形成一个圆圈
ConLs

并在circle_up(Ls,Circle):- head(A,Ls), append(Ls,[A],Circle). 的简单调用中使用Circle来完成append的定义。这假定了定义

left/3