2011-11-11 7 views
5

Powiel możliwe:
Prolog delete: doesn't delete all elements that unify with ElementUsuwanie wszystkich członków listy bez unifikacji w Prologu

W Prologu jeśli piszesz tak:

delete([(1,1),(1,2),(1,1),(3,4)],(1,_),L). 

wynik będzie:

L = [ (1, 2), (3, 4)]. 

Co jest normalne, ponieważ zmienna _ wiąże się z 1 w pierwszym elemencie i szuka dalszych elementów (1,1) i usuwa je.

Czy istnieje sposób na uniknięcie tego zjednoczenia i usunięcie wszystkich członków formularza (1, _). W takim przypadku wynik musi być: L = [(3, 4)].

Odpowiedz

3
delete_pattern([], _, []). 
delete_pattern([H|T], P, O) :- 
    ( H \= P 
    -> O = [H|O1], 
     delete_pattern(T, P, O1) 
    ; delete_pattern(T, P, O)). 

może chcesz korzystać z innych predykatów do filtrowania, który powodowałby w nieco inny semantyki jak ==/2 lub [email protected]=/2.

+0

Works w zasadzie, ale przerwy jeśli elementy listy są niewystarczająco wystąpienia w czasie 'delete_pattern/3' jest prowadzony. – repeat

3

Oto kolejna wersja. Właściwie, to czysta jeden:

list_el_deleted([], _, []). 
list_el_deleted([X|Xs], X, Ys) :- 
    list_el_deleted(Xs, X, Ys). 
list_el_deleted([X|Xs], E, [X|Ys]) :- 
    dif(X,E), 
    list_el_deleted(Xs, E, Ys). 

Próbując go na zapytaniu ujawnia rzeczywiste źródła dwuznaczności w swoim oświadczeniu problem:

?- list_el_deleted([(1,1),(1,2),(1,1),(3,4)],(1,X),L). 
X = 1, 
L = [ (1, 2), (3, 4)] ; 
X = 2, 
L = [ (1, 1), (1, 1), (3, 4)] ; 
L = [ (1, 1), (1, 2), (1, 1), (3, 4)], 
dif(X, 1), 
dif(X, 2), 
dif(X, 1). 

Więc to wszystko zależy od tego, co X rzeczywiście jest: 1, 2, albo coś innego. Zauważ, że poprzednie wersje omawiane tutaj są uzależnione od rzeczywistego instancji co sprawia rozumowanie znacznie trudniejsze:

?- delete([a],X, Xs), X = c. 
false. 

?- X = c, delete([a],X, Xs). 
X = c, 
Xs = [a]. 
+1

@repeat: Umieść swoje rozwiązanie [tutaj] (http://stackoverflow.com/questions/8100586/prolog-delete-doesnt-delete-all-elements-that-unify-with-element#). – false