Prolog 删除元素的第二个和第三个引用

Prolog 删除元素的第二个和第三个引用,prolog,Prolog,我想制作一个程序,给定一个列表L,其中元素X出现3次,它只返回一次包含它的NL列表。 比如说这个问题, ?- erase([1,2,3,1,6,1,7],1,NL). 应该回来 NL = [1,2,3,6,7] or NL = [2,3,1,6,7] or NL = [2,3,6,1,7] 附言。 假设给定列表不包含任何元素2、4次或更多次。 这是我的代码,但当我提问时返回false。如有任何更正建议,将不胜感激 erase([],_,[]). erase(L,X,NL):-

我想制作一个程序,给定一个列表L,其中元素X出现3次,它只返回一次包含它的NL列表。 比如说这个问题,

?- erase([1,2,3,1,6,1,7],1,NL).
应该回来

NL = [1,2,3,6,7]  or  NL = [2,3,1,6,7]  or  NL = [2,3,6,1,7]
附言。 假设给定列表不包含任何元素2、4次或更多次。
这是我的代码,但当我提问时返回false。如有任何更正建议,将不胜感激

erase([],_,[]).
erase(L,X,NL):-
                append(A,[X,B,X,C,X,D],L),
                append(A,[X,B,C,D],NL).

因此,您认为下面的查询应该成功,但失败了

?- erase([1,2,3,1,6,1,7],1,NL).
false.
即使以下概括也失败了:

?- erase([1,2,3,1,6,1,7],E,NL).
false.
让我重新表述一下,以便于访问:

?- L = [1,2,3,1,6,1,7], erase(L,E,NL).
false.
所以我们现在必须进一步推广这个列表。我可以一个元素一个元素地尝试,但我更喜欢先:

?- L = [_,_,_,_,_,_,_], erase(L,E,NL).
L = [_2528, E, _2540, E, _2552, E, _2564],
NL = [_2528, E, _2540, _2552, _2564] ;
false.
这是唯一的答案。它告诉我们,
E
必须正好出现在第2、第3和第5位。如果这是真的,让我们试试:

?- erase([0,1,0,1,0,1,0],1,NL).
NL = [0, 1, 0, 0, 0] ;
false.
所以你的解决方案有时是有效的。你似乎更想:

erase(L, X, NL) :-
   phrase(
      ( seq(Any1), [X], seq(Any2), [X], seq(Any3), [X], seq(Any4) ), L),
   phrase(
      ( seq(Any1),      seq(Any2),      seq(Any3), [X], seq(Any4) ), NL).

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).

append/2在处理多个列表时有很大帮助:

erase(L,E,R) :-
    append([A,[E],B,[E],C,[E],D],L),
    select([E],[X,Y,Z],[[],[]]),
    append([A, X, B, Y, C, Z, D],R).

如果发生四次呢?我们可以只找
1
?或者删除所有多次出现的元素?正如我在P.S中所写的,假设这种情况不存在,我将从duck调试开始:告诉(你的橡皮鸭,或者我们)你的谓词的目的是什么。为什么在这里使用
append/3
?为什么你认为这是解决这个问题的好工具?是的,你所说的是经典的策略,但我认为append可以完成这项工作,即使行数更少。你同意吗?它只适用于特定的列表模式。列表中的
B
是一个元素。因此,这意味着您的列表
[1,2,3,1,6,1,7]
无法处理,因为在第一个和第二个1之间有两个元素:
2
3
。很好的一点是,无论X元素位于何处,它都应该起作用。幸运的是,你的建议行得通,但你能让我的建议也行吗?我的意思是用append/3。谢谢你迄今为止的帮助@有点兴奋:这很复杂:你至少需要6(六)个
append/3
goalsOh,我马上就拒绝了。