在Prolog中使用累加器方法从列表中删除偶数元素



我正在尝试编写一个程序,以相对优雅的方式从prolog列表中删除偶数元素。我的想法是使用累加器。也就是说,我有一个列表,一开始是空的,然后通过砍掉偶数元素逐渐建立列表。为了给大家一些直观的印象,我受到了下面这个程序的启发,这个程序用于对列表中的元素进行反转:

accRev([],A,A).
accRev([H|T],A,R) :- accRev(T,[H|A],R).

现在我的想法是:

without_even([],A,A).
without_even([H|T],A,N) :-
H mod 2 == 0,
without_even(T,[H|A],N).

我们首先将一个空列表传递给A,因此,我们的想法是,我们希望列表N使N = A,其中A是遍历[H|T]并砍掉所有偶数头的结果。但是当我用

进行测试时
?- without_even([1,2],[],N).

我得到假。我想知道是否有人可以在这里帮助我的直觉-我使用Prolog两天-这样我就可以朝着一个解决方案工作。

我的直觉告诉我,当头部为偶数时,我需要另一个子句。

编辑:

我已经设法让它工作与以下程序:

without_even([],A,A).
without_even([H|T],A,N) :- 
H mod 2 == 0, without_even(T,[H|A],N).
without_even([H|T],A,N) :-
H mod 2 =:= 0, without_even(T,A,N).

要删除偶数,只需:

remove_even( []     , []     ) .
remove_even( [X|Xs] ,    Ys  ) :- X rem 2 =:= 0, !, remove_even(Xs,Ys) .
remove_even( [X|Xs] , [X|Ys] ) :-                   remove_even(Xs,Ys) .

或者更优雅的:

remove_even( Xs , Ys ) :- findall( X , ( member(X,Xs), X rem 2 == 0 ), Ys ).

另一个解决方案:

remove_even([], []).
remove_even([X|Xs], Zs) :-
R is X mod 2,
remove_even_case(R, X, Ys, Zs),
remove_even(Xs, Ys).

remove_even_case(0, X, Ys, [X|Ys]).   
remove_even_case(1, _, Ys, Ys).

最新更新