I keyed in my facts:
likesdrinking(tom).
likesdrinking(sally).
likesdrinking(holly).
likespainting(tom).
likespainting(sally).
likespainting(chad).
likespainting(margo).
likesskating(tom).
likesskating(holly).
likesskating(margo).
likesskating(matt).
likesskating(cass).
If I want to find those who likes drinking or painting or skating, i would use the findall method which is:
findall(X,(likesdrinking(X),likesskating(X),likespainting(X)),X).
and it will give me the result for those who likes more than once. X= tom, sally, holly, tom, sally, chad .... etc
But how do I make it so that it will only return one answer instead of duplicates? so it would be
X = tom, sally, holly, chad, margo, matt , cass
You want the standard setof/3 predicate:
?- setof(X, (likesdrinking(X),likesskating(X),likespainting(X)), L).
L = [tom].
?- setof(X, (likesdrinking(X),likesskating(X)), L).
L = [holly, tom].
?- setof(X, (likesdrinking(X),likespainting(X)), L).
L = [sally, tom].
As David noted in his comment, if you want to construct a list of people that like at least one those activities (without duplicates):
?- setof(X, (likesdrinking(X); likesskating(X); likespainting(X)), L).
L = [cass, chad, holly, margo, matt, sally, tom].
For questions like "who likes skating but not drinking", you have to be careful with the order of the goals. The following query is wrong:
?- setof(X, (\+ likesdrinking(X), likesskating(X)), L).
false.
Why? The variable X is not bound when you call \+ likesdrinking(X), which will fail as there's several people that like drinking. You will need to write instead:
?- setof(X, (likesskating(X), \+ likesdrinking(X)), L).
L = [cass, margo, matt].
The likesskating(X) goal will bound X and then the \+ likesdrinking(X) will check that that specific person doesn't like drinking. In general, be careful when using the negation (\+/1) with non-ground goals.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With