Eliminate consecutive duplicates of list elements with prolog

你离开我真会死。 提交于 2020-12-15 05:23:07

问题


The original problem was to come up with a way to get the following

remove([a,a,a,b,q,q,q,q,e,e,e]),X)
X = [a,b,q,e]

回答1:


We can solve this problem by one iteration along the list. At any point in the list we check the current element and the next element, if they are the same then we ignore the current element, else if they are different we take the current element.

rm_dup([], []).
rm_dup([X], [X]).
rm_dup([X1, X2 | Xs], [X1 | Ys]) :-
    dif(X1, X2), rm_dup([X2|Xs], Ys).
rm_dup([X, X | Xs], Ys) :-
    rm_dup([X | Xs], Ys).

The first and second clauses are base clauses in which there are no duplicate elements. The third and fourth clauses are recursive rules.

In third clause we state that if the input list has two values X1 and X2 and they are different dif(X1, X2), then keep the current value.

In fourth clause if we have same consecutive values then we ignore the current value.

The third and fourth clauses are mutually exclusive and hence to make the predicate deterministic it is better to combine them as follows

rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
    dif(X1, X2) -> (rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1]);
    rm_dup([X2 | Xs], Ys).

Even better is to just use equality as a condition and flip the then and else clauses.

rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
    X1 = X2 ->  rm_dup([X2 | Xs], Ys);
    rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1].



回答2:


Kinda long, but this solved it.

delete(_,[],[]).
delete(X,[X|T],R):- delete(X,T,R).
delete(X,[H|T],[H|R]) :- delete(X,T,R).

remove([],[]).
remove([H|T], [H|R]) :- 
    member(H,T),!,
    delete(H,T,R1),
    remove(R1,R).

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



回答3:


You can simply use sort.

First: In the base class if the List are empty stop.

Second: In the second predicate, take the list and sort it. Display the answer in K.

remove_extras([],[]).
remove_extras([H|T],K):-
    sort([H|T], K).

?-remove_extras([a,a,a,b,q,q,q,q,e,e,e],X).
X = [a, b, e, q]

?-remove_extras([1,3,2,5,1,6,1,2,7],X).
X = [1, 2, 3, 5, 6, 7]

If you don't want to use sort, you can use the following predicates: Remove duplicates checks for elements existing more than once and keeps them in the list.

First: The base case says that if the lists are empty stop.

Second: The second predicate checks if an element exist in the remaining list (member) then don't add it to the final list.

Third: The third predicate says, if the element is in not the remaining list then add it to the final list.

remove_duplicates([],[]).
remove_duplicates([H | T], List) :-    
     member(H, T),
     remove_duplicates( T, List).

remove_duplicates([H | T], [H|T1]) :- 
     \+ member(H, T),
      remove_duplicates( T, T1).


来源:https://stackoverflow.com/questions/65046171/eliminate-consecutive-duplicates-of-list-elements-with-prolog

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!