4

I'm learning Prolog right now and the recursive thinking is difficult to me.

I have two lists e.g. L1=[1,2,3] and L2=[3,1,2] and I should check if all elements of L1 are contained in L2

So allMembers(L1,L2). should return true and allMembers(L1,[2,3,4]). should return false, because there is no 4 in L1

I thought it would be possible to get the head of the one list and return true if it finds that element in the other list (by splitting it down until the list only contains one item), but I have no idea how to do that in Prolog.

It would be nice if you could help me getting faster on the uptake (?)

I found similar problems here, but couldn't find an answer to my specific problem :/

Edit:
I now have:

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

which I need to use for any element in L1 to L2

Rasalas
  • 1,552
  • 2
  • 12
  • 15
  • 2
    Did you mean to say that `allMembers` is true iff both lists contain the same elements, but not necessarily in the same order? What about duplicates? – Scott Hunter Nov 05 '15 at 20:51
  • good question, the task is written like a documentation (translated from german to english): `allMembers(L1,L2). % checks if all elements in L1 are available in L2`. I guess duplications are irrelevant if all the elements from list `L1` are in `L2` – Rasalas Nov 05 '15 at 21:13
  • 1
    So that also means `L2` could contain elements that are not in `L1`. – lurker Nov 05 '15 at 21:19
  • yes, there is no further explaination that would say otherwise. – Rasalas Nov 05 '15 at 21:28

5 Answers5

5

Quick solution using de facto standard predicates:

all_from_first_in_second(List1, List2) :-
    forall(member(Element,List1), member(Element,List2)).
Paulo Moura
  • 18,373
  • 3
  • 23
  • 33
3

Probably the simplest way to define it may be:

% contained_in(L1, L2) succeeds if all elements of L1 are contained in L2
contained_in(L1, L2) :- maplist(contains(L2), L1).
contains(L, X) :- member(X, L).

maplist/2 will apply contains(L2) to each element of L1, and will succeed if every call succeeds. contains/2 is like member/2 but puts the arguments in the order that make it work with maplist.

lurker
  • 56,987
  • 9
  • 69
  • 103
  • Thanks for your work - it works, but I don't think I can use that since we never talked about `maplist/2`, `contains/2` or `member/2`. We only talked about the very first principles... – Rasalas Nov 05 '15 at 21:44
  • 1
    @Rasalas you can then use your own `member/2` and write a predicate that acts like `maplist/2` in this case. It doesn't have to have the generality of `maplist/2`, but just recurses through each element of your list, checking the `member` condition as shown. – lurker Nov 05 '15 at 21:49
2

To solve your sub-problem: member(A,B) is true if A is a member of the list B.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • that took me a bit further, thanks. I don't know why I didn't get that. I now have `member(X,[X|_]).` and `member(X,[_|T]):- member(X,T).` which seems to work. Now I need to use this rule for any element in `L1`, which will need some time with my sleepy brain :) – Rasalas Nov 05 '15 at 21:07
  • 1
    @Rasalas `member/2` is a pre-defined predicate in Prolog, so best not to redefine it. `member(A, B)` succeeds if `A` is an element in list `B`. If you need a different predicate behavior, you should write a different predicate name. – lurker Nov 05 '15 at 21:20
1

Simply use list_permuted/2 like this:

?- list_permuted([1,2,3],[3,1,2]).
true.

Note that list_permuted/2 demands that both lists have the same items in the same quantity!

Community
  • 1
  • 1
repeat
  • 18,496
  • 4
  • 54
  • 166
  • 1
    Except I think the second list is supposed to be allowed to have elements that are not in the first list. – lurker Nov 05 '15 at 21:50
1

This solves the question with only self defined predicates:

% allMembers(L1,L2) checks if all elements of L1 are available in L2
% solve the sub problem
isMemberOf(X,[X|_]).
isMemberOf(X,[_|T]):- isMemberOf(X,T).

% iterate through 'L1' and ask if the member exists in 'L2'
allMembers([],_).
allMembers([H|T],L):- allMembers(T,L), isMemberOf(H,L).
Rasalas
  • 1,552
  • 2
  • 12
  • 15