I am having trouble understanding prolog, I have to find if X is before Y in a list.
so I have a base case with an empty list
before(X, Y, [ ]).
<
Here's a simple solution that uses no built-in predicates whatsoever.
It helps if you re-cast the problem in somewhat more generic terms.
A common prolog idiom is a public predicate that invokes a worker predicate that does all the work. Often, the worker predicate will carry additional variable that maintain state. In this case, we don't need to maintain state, but it simplifies things if we make the actual solution more generic: instead of defining the problem in terms of X
and Y
, redefineit in terms of a list of arbitrary length, defining the order in which things must be found in the target list.
Then, it's simply a matter of recursing down both lists in parallel to determine if the precedence constraints are satisfied. The generic solution (which will work for a list containing an arbitrary number of constraints) has 3 cases:
- The constraint list is empty: Success!
- The head of the constraint list unifies with the head of the list being tested. That indicates that a constraint has been satisfied. Remove both the constraint and the item it just matched (the head of the list being tested) and recurse down.
- Finally, just remove the head of the list being tested and recurse down.
The solution looks like this:
x_before_y( X , Y, Zs ) :- satisfies_constraints( [X,Y] , Zs ) .
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- satisfies_constraints(Cs,Xs) .
satisfies_constraints( Cs , [_|Xs] ) :- satisfies_constraints(Cs,Xs) .
On backtracking, this will find all possible solutions. If that's not desirable, a cut in the 2nd clause will eliminate the choice points:
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- !, satisfies_constraints(Cs,Xs) .
satisfies_constraints( Cs , [_|Xs] ) :- satisfies_constraints(Cs,Xs) .
As will introducing a test for non-unifiability in the 3rd clause:
satisfies_constraints( [] , _ ) .
satisfies_constraints( [C|Cs] , [C|Xs] ) :- satisfies_constraints(Cs,Xs) .
satisfies_constraints( [C|Cs] , [X|Xs] ) :-
C \= X ,
satisfies_constraints([C|Cs],Xs)
.