编写一个实现以下功能的PROLOG程序(即谓词集)。程序应该比较三个列表,并确定第一个列表的第一个元素是否与第二个列表的最后一个元素以及第三个列表的倒数第二个元素相同。调用主谓词:compare(List1,List2,List3)。
我继续为两个单独的条件编写了单独的代码,这些代码可以单独工作。 1. List1的第一项等于List2的最后一项。 2. List1的第一项等于List3的第二项。
现在我很难将代码组合在一起使用。我的思路是,必须先满足条件1和条件2才能总体满足条件。所以以某种方式我必须在同一程序中单独运行条件1和条件2的代码?如果两个都返回true,那么我可以说其他条件满足我的条件。
compare(List1,List2,List3):- last(true), secondLast(true).
条件1:
last([HeadList1|RestList1],[HeadList1]).
last([HeadList1|RestList1],[HeadList2|RestList2]) :-
last([HeadList1|RestList1],RestList2).
条件2:
secondLast([HeadList1|RestList1],[HeadList1,RestList3]).
secondLast([HeadList1|RestList1],[HeadList3|RestList3]) :-
secondLast([HeadList1|RestList1],RestList3).
我期望的是:
?- compare([2,8,9,1],[4,5,6,2],[1,2,3]).
yes
?- compare([a,b,c,d,k],[a,c,f,e],[a,s]).
no
答案 0 :(得分:1)
使用SWI,您可以使用last/2
和secondTast/2
from this question的定义:
secondLast([X,_], X).
secondLast([_|T], X) :- secondLast(T, X).
my_compare([H|_],L1,L2):-
last(L1,H),
secondLast(L2,H).
?- my_compare([2,8,9,1],[4,5,6,2],[1,2,3]).
true
?- my_compare([a,b,c,d,k],[a,c,f,e],[a,s]).
false
您可以在第一个查询中删节以避免错误的解决方案。这是第一个解决方案,您可能会非常喜欢并使用例如reverse/2
和其他谓词来查找另一个解决方案(但可能会更慢)。
答案 1 :(得分:1)
@damianodamiano建议使用reverse/2
的实现,我认为了解它的含义可能会很有趣。
mycompare([H|_], L2, L3) :-
reverse(L2, [H|_]),
reverse(L3, [_, H|_]).
reverse/2
比遍历列表要贵一些,因此这可能不是解决问题的最佳方法,我认为值得一看,因为它与上述问题相当接近,并且可以证明该问题只有通过统一才能真正解决。 damianodamiano的解决方案具有类似的属性,因为您发现第一件事H
,然后表明H
出现在其他两个列表的其他位置。
现在,我为您提供了一些其他反馈:
您完全可以相信,如果您有两个谓词,例如p1
和p2
,则可以通过进行p1, p2
来组合它们。通常,它们将在它们之间共享变量绑定,因为您在Prolog编程中所做的是建立某些事物之间的关系。
这也是为什么单例“警告”实际上是错误的原因:它们揭示了您认为存在关联但Prolog可以告诉您在任何地方都没有共享变量的情况,因此没有建立关联。
您的变量名确实不好。如果您所有变量名的99%都相同,那么您将感到困惑。使用A
和B
比HeadList1
和HeadList2
更好。如果必须使用此类名称,请简化为H1
和H2
。当您看到[X|Y]
时,便知道X是列表的开头,而Y
是列表的结尾,则无需将该信息作为名称的一部分。如果可以的话,请专注于变量的内容,或尝试在变量所属的表达式之间建立关系。
Prolog谓词不“返回true”。它们可以成功或失败,但是它们的评价不像函数:不能mycompare(A,B,C)
代替true
,而仅mycompare(A,B,C)
成功,不能为结果R = mycompare(A,B,C)
赋值,并且您不能嵌套writeln(mycompare(A,B,C))
之类的谓词。因此,现在就养成这种习惯,这样以后就不会再感到困惑了。