列表的最后一个成员是内存位置

时间:2014-01-05 17:38:19

标签: prolog

我不明白为什么对于这个谓词,最后一个位置是记忆位置。

elimina_diretos(_,[],_).
elimina_diretos(LA,[H|T],LP):-
    member(H,LA),
    elimina_diretos(LA,T,LP).
elimina_diretos(LA,[H|T],[H|LP]):-
    elimina_diretos(LA,T,LP).

如果我输入

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

Prolog给了我:

L = [pedro, rocha|_G609] ;

如何清除_G609

3 个答案:

答案 0 :(得分:2)

您的计划存在一些问题。但首先,_G609只是一个逻辑变量。您可以假设此数字与具体内存位置有些相关。这种在顶层指示变量的特殊方式特定于SWI-Prolog。其他系统产生更全面的结果,例如GNU Prolog:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro,rocha|_] ? ;

因此,此回答意味着Lpedrorocha开始的部分列表。这是你的意图吗?这也意味着

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).
true ?

这真的是你的意图吗?我想不是。但由于你没有说明关系应该描述什么,所以很难猜测。

这不是您的程序的唯一问题。我们只看了第一个答案,但让我们看看后续的答案!

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha|_] ? ;

L = [pedro,rocha,andre|_] ? 

yes

所以还有另一个答案!

这是一种非常通用的快速查找此类错误的方法。测试时,从最常见的查询开始,详细查看答案:

| ?- elimina_diretos(A, B, C).

B = [] ? ...

这意味着:elimina_diretos/3对于所有 AC B = []为真。我非常怀疑这是你想要描述的内容。


((因为每个人都只发布答案,我必须效仿))

elimina_diretos(_,[],[]).
elimina_diretos(LA,[H|T],LP):-
    member(H,LA),
    elimina_diretos(LA,T,LP).
elimina_diretos(LA,[H|T],[H|LP]):-
    maplist(dif(H),LA),
    elimina_diretos(LA,T,LP).

此解决方案不依赖于(未指定)模式。 @ mbratch和@ CapelliC的解决方案确实依赖(不知何故)并且错误地失败了:

?- elimina_diretos([X], [pedro,tiago],[pedro]).
X = tiago ;
false.

答案 1 :(得分:1)

首先改变:

elimina_diretos(_,[],[]).

请注意,您的代码必须是确定性的,否则您将在回溯中获得不需要的“解决方案”:

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
L = [pedro, rocha, andre] ;
...

然后第二次改变(注意切割):

elimina_diretos(LA,[H|T],LP):-
    memberchk(H,LA),!,
    elimina_diretos(LA,T,LP).

现在应该按预期工作

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
false.

使用memberchk/2代替member/2,效率更高。

答案 2 :(得分:1)

只是为了给几个好的答案留下另一个选择。

正如CapelliC已经指出的那样,一个问题是基本情况不太正确:elimina_diretos(_, [], _).这说明从空列表中删除任何一组项目,我得到一个匿名变量。在这种情况下,正确的“答案”将是空列表:elimina_diretos(_, [], []).

这是唯一的变化,然后您可以通过CapelliC提到的多重解决方案问题获得良好的答案。

重写条款的另一个选择如下:

elimina_diretos([], L, L).             % Remove nothing from L is L
elimina_diretos([H|T], L, LP):-
    (   delete(H, L, L1)             % L1 is L with all H's removed
    ->  elimina_diretos(T, L1, LP)
    ;   elimina_diretos(T, L, LP)    % There are no H's in L
    ).

产生:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha] ? ;

no

| ?- elimina_diretos([a,b,c], [a,c,e,f], L).

L = [e,f]

yes

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).

no

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,andre]).

no