Reputation: 13
I have this clause that says an object is directly before another object in the list. I'm looking for guidance on how to generalize this to be an object that is any location before the object in the list (not necessarily to the left of it immediately). Then I want to be able to also check for after as well.
% Checks that `X` comes before `Y`
% in the list `Ds`
before(X,Y,Ds) :-
remainder(X,Ds,Rs),
member(Y,Rs).
% Finds a member of a list and
% unifies the third parameter such
% that it is the remaining elements in
% the list after the found member
remainder(X,[X|Ds],Ds).
remainder(X,[_|Ds],Rs) :- remainder(X,Ds,Rs).
Upvotes: 1
Views: 69
Reputation: 18726
That's the right hunch: member/2
can be put to use for that.
You were probably thinking about writing something like this:
before(A,Z,[A|Xs]) :- member(Z,Xs).
before(A,Z,[_|Xs]) :- before(A,Z,Xs).
Sample query using SICStus Prolog 4.5.1:
| ?- before(2,X,[1,2,3]). X = 3 ? ; no
And here's another query, this one even a bit more general:
| ?- before(A,Z,[1,2,3,4]). A = 1, Z = 2 ? ; A = 1, Z = 3 ? ; A = 1, Z = 4 ? ; A = 2, Z = 3 ? ; A = 2, Z = 4 ? ; A = 3, Z = 4 ? ; no
Upvotes: 1
Reputation: 10102
before(X,Y, Ds) :-
phrase(( ..., [X], ..., [Y], ... ), Ds).
... --> [] | [_], ... .
Upvotes: 1
Reputation: 60004
if you are not doing this for learning, you can use append/2:
before(X,Y,Ds) :-
append([_,[X],_,[Y],_],Ds).
?- before(2,X,[1,2,3]).
X = 3 ;
false.
Upvotes: 0