0
votes

I am trying to write a Prolog code, but I can't get this to return true. I am trying to find a list, which all elements are included in two other lists. For example all list A elements are found in B and C lists each, not together. My Prolog code is :

member(X, [X|_]).   
member(X, [_|T]) :-
    member(X, T).

first([H0|T0], [H0|T1], A) :-
    member(H0, A),
    first(T0, [H0|T1], A).
first([H0|T0], [_|T1], A) :-
    first([H0|T0], T1, A).

where member predicate returns true if an element is in a list. With predicate 'first' I am trying to use member predicate to find a matching element of A and B in C list. If I find, then go further in the first list and compare its first element to second lists elements and again, if I would matching, I check with if I can find it in third list. I hope it does this, but when I run

?- first([4, 6, 4], [4, 5, 6, 4], [1, 2, 4, 6]).

it gives false and I can't figure out why. This seems as a simple attention mistake somewhere, but I just can't get my head around it.

2
You seem to lack a base case for empty lists.Hermann Döppes

2 Answers

1
votes

I don't know anything about prolog, but like everyone I've been bitten by logic errors before. (=

As I have commented, you seem to lack a base case for first([], _, _). An example:

first([4], [4], [4]) :-
    member(4, [4]), // quite true
    first([], [4], [4]). // No matching rule, as all those assume an existing head in the first argument
0
votes

I am not sure I understood your question, but allow me to try to specify further your predicate first/3:

first(+L, +L1, +L2)
  succeeds if every element of L is found either in L1 or in L2.

If this is what you're looking for, then:

first([], _, _).
first([E|L], L1, L2) :-
  (member(E, L1); member(E, L2)),
  first(L, L1, L2).

Examples of success:

first([1, 2, 3], [1, 2, 3], [1, 2]).
first([1], [1, 2, 3], [1, 2]).
first([1, 2, 3], [1, 2, 3], []).

Examples of faiure:

first([1, 2, 3, 5], [1, 2, 3], [1, 2]).
first([7], [1, 2, 3], [1, 2]).
first([1, 2, 3], [], []).