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

2

5

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

Dennet answered 11/11, 2011 at 22:18 Comment(0)
D
4
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.

Dundee answered 12/11, 2011 at 8:15 Comment(1)
Works in principle, but breaks if list items are insufficiently instantiated at the time delete_pattern/3 is run.Slapstick
S
3

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].
Stack answered 12/11, 2011 at 17:38 Comment(1)
@repeat: Put your solution here.Stack

© 2022 - 2024 — McMap. All rights reserved.