프롤로그로 목록 요소의 연속 중복 제거

Nov 27 2020

원래 문제는 다음을 얻을 수있는 방법을 찾는 것이 었습니다.

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

답변

1 rajashekar Nov 28 2020 at 05:20

목록을 따라 한 번 반복하면이 문제를 해결할 수 있습니다. 목록의 어느 시점에서든 현재 요소와 다음 요소를 확인합니다. 동일한 경우 현재 요소를 무시하고 다른 경우 현재 요소를 사용합니다.

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).

첫 번째 및 두 번째 절은 중복 요소가없는 기본 절입니다. 세 번째와 네 번째 절은 재귀 규칙입니다.

세 번째 절에서 입력 목록에 두 개의 값이 X1있고 X2서로 다른 dif(X1, X2)경우 현재 값을 유지 한다고 명시합니다 .

네 번째 절에서 동일한 연속 값이 있으면 현재 값을 무시합니다.

세 번째 및 네 번째 절은 상호 배타적이므로 술어를 결정적으로 만들려면 다음과 같이 결합하는 것이 좋습니다.

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).

더 좋은 방법은 평등을 조건으로 사용하고 thenelse 절을 뒤집는 입니다.

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].
a3yko Nov 28 2020 at 03:41

조금 길지만 이것이 해결되었습니다.

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).