Вы можете использовать maplist
для такого рода проблем, так как он следует за стандартным рекурсивным обходом списка:
mem(L, X) :- memberchk(X, L).
subset(S, L) :- maplist(mem(L), S).
Результаты:
| ?- subset([a,c], [a,b,c,d]).
yes
| ?- subset([c,a], [a,b,c,d]).
yes
| ?- subset([e], [a,b,c,d]).
no
| ?- subset([], [a,b,c,d]).
yes
| ?- subset(S, [a,b,c,d]), S=[_|_].
S = [a] ? ;
S = [a,a] ? ;
S = [a,a,a] ? ;
...
Обратите внимание, что оригинальное определение проблемы делаетНе исключаю случая, когда подмножество может иметь повторяющиеся элементы из надмножества.Если вы хотите ограничить подмножества количеством элементов, меньшим или равным количеству надмножеств, вы можете использовать select/3
:
subset([], _).
subset([X|Xs], L) :-
select(X, L, L1),
subset(Xs, L1).
Результаты:
| ?- subset([a,c], [a,b,c,d,e]).
true ? ;
no
| ?- subset([a,f], [a,b,c,d,e]).
no
| ?- subset([a,a], [a,b,c,d,e]).
no
| ?- subset(S, [a,b,c]), S=[_|_].
S = [a] ? ;
S = [a,b] ? ;
S = [a,b,c] ? ;
S = [a,c] ? ;
S = [a,c,b] ? ;
S = [b] ? ;
S = [b,a] ? ;
...
S = [c,b] ? ;
S = [c,b,a] ? ;
no
обратите внимание, что список [c,b,a]
считается другим списком в Прологе по сравнению с [a,b,c]
, поэтому это отдельное решение.Если вы хотите, чтобы списки вели себя как наборы, это другое решение.