Prolog中简单递归任务的问题

时间:2019-03-11 03:19:57

标签: recursion prolog

我目前正在解决序言中的一些问题,但似乎无法解决关于递归的一个问题,因此向我介绍了此表:Gryffindor Table

鉴于这些信息,我用以下内容制作了自己的知识库:

/*
 This order represents how they are sit from left to right
 parvati_patil is left to lavender_brown,
 lavender_brown is left to neville_longbottom
 and so on, until we reach parvati again at the end.
*/

seatedTogether(parvati_patil, lavender_brown).
seatedTogether(lavender_brown, neville_longbottom).
seatedTogether(neville_longbottom, alicia_spinnet).
seatedTogether(alicia_spinnet, fred_weasley).
seatedTogether(fred_weasley, george_weasley).
seatedTogether(george_weasley, lee_jordan).
seatedTogether(lee_jordan, dennis_creevey).
seatedTogether(dennis_creevey, dean_thomas).
seatedTogether(dean_thomas, ginny_weasley).
seatedTogether(ginny_weasley, angelina_johnson).
seatedTogether(angelina_johnson, seamus_finnigan).
seatedTogether(seamus_finnigan, colin_creevey).
seatedTogether(colin_creevey, harry_potter).
seatedTogether(harry_potter, hermione_granger).
seatedTogether(hermione_granger, ron_weasley).
seatedTogether(ron_weasley, natalie_mcdonald).
seatedTogether(natalie_mcdonald, katie_bell).
seatedTogether(katie_bell, parvati_patil).

% X is left to Y if they are seatedTogether(X,Y)
isAtLeft(X,Y):-seatedTogether(X,Y).
% X is right to Y if they are seatedTogether(Y,X)
isAtRight(X,Y):-seatedTogether(Y,X).

/*
 This rule just tells us who X is two places away from Y,
 X is two places away from Y if 
 X is seatedTogether(X,Z)
 and that Z is seatedTogether(Z,Y).
*/
twoPlacesAway(X,Y):-seatedTogether(X, Z), seatedTogether(Z,Y).

/*
  This rule just tells us whos sitting @ the table
  by just unifying X with the values of seatedTogether(X,Y)
  without regarding Y.
*/
atTable(X):-seatedTogether(X,_).


/*
  Between two:
  Its supposed to tell us whos Z is between X and Y
  The perfect case (for me) would be that X and Y are sitting
  together, so they have no one in the middle.
  The other way around would be that
  X is not equal to Y
  X1 is sitting left to X,
  and then we call it again with
  X1, Y and Z1 as args,
  after each call, we equal
  Z to X1 value.
*/
betweenTwo(X,Y,Z):-isAtLeft(X,Y),isAtRight(Y,X).
betweenTwo(X,Y,Z):-
    X \= Y,
    isAtLeft(X, X1),
    betweenTwo(X1, Y, Z1),
    Z = X1.

问题出在最后一个规则定义上,如果我这样称呼它:

betweenTwo(ron_weasley, alicia_spinnet, Z).

Z的值应为:

  • natalie_mcdonald,
  • katie_bell,
  • parvati_patil,
  • lavender_brown,
  • neville_longbottom。

但是Z仅与

的值统一
  • natalie_mcdonald。

我相信我已经非常接近它了,但是我真的迷失了那个规则出了什么问题。我将其定义为使X逐步等于Y的值,但在Y之前的值应处于理想情况并停止移动,并统一之前的其余元素。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

首先:您的基本案例(您称之为“完美案例”)说:“如果X位于Y的左侧,而Y位于X的右侧,则每个Z都在它们之间”,而不是“在它们之间没有人”(条件也是多余的)。基本情况应说明谓词成立的时间(即,某些ZXY之间),而不是当谓词不成立时。另请参见以下答案:https://stackoverflow.com/a/3001941/9204

第二:在非基础情况下,您有

isAtLeft(X, X1),
betweenTwo(X1, Y, Z1),
Z = X1.

当Prolog在X1中搜索isAtLeft(ron_weasley, X1)时,唯一的答案是natalie_mcdonald,随后的Z = X1也迫使Z也成为natalie_mcdonald

所以这部分代码等同于

isAtLeft(X, Z),
betweenTwo(Z, Y, Z1).

或用词“ ZXY之间,如果:X不等于YX直接等于Z的左侧,并且某些Z1ZY“之间,这是没有道理的。

您还应该注意有关单例变量Z1的警告。