Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting all members of a list without unification in Prolog [duplicate]

Possible Duplicate:
Prolog delete: doesn't delete all elements that unify with Element

In Prolog if you write this:

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

the result will be:

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

What is normal because the _ variable binds with 1 in the first element and it searches for further elements of (1,1) and deletes them.

Is there a way to prevent this unification from happening and deleting all members of the form (1,_). In that case the result must be: L = [ (3, 4)].

like image 642
Willem Van Onsem Avatar asked Nov 11 '11 22:11

Willem Van Onsem


2 Answers

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

You may like to use other predicates for filtering that would result in slightly different semantics as ==/2 or =@=/2.

like image 70
salva Avatar answered Sep 24 '22 21:09

salva


Here is a another version. Actually, a pure one:

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

Trying it on your query reveals the actual sources of ambiguity in your problem statement:

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

So it all depends on what X actually is: 1, 2, or something else. Note that the previous versions discussed here depend on the actual instantiation which makes reasoning much more difficult:

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

?- X = c, delete([a],X, Xs).
X = c,
Xs = [a].
like image 24
false Avatar answered Sep 24 '22 21:09

false