0
votes

I'm a begginer at Prolog and I need some help with this exercise, this is the knowledge base provided:

album(‘R. Stevie Moore’, ‘Manuscription’).   
album(‘Lane Steinberg’, ‘Manuscription’).  
album(‘R. Stevie Moore’, ‘The Yung & Moore Show’).  
album(‘Yukio Yung’, ‘The Yung & Moore Show’).  
album(‘Jessie Evans’, ‘Autonervous’).  
album(‘Bettina Koster’, ‘Autonervous’).  
album(‘Lucia Pamela’, ‘Walkin on the moon’).  
album(‘Shooby Taylor’, ‘The Human Horn’).  
album(‘Tiny Tim’, ‘God Bless Tiny Tim’).  
album(‘The Legendary Stardust Cowboy’, ‘Rock-It to Stardom’).  
vinil(‘Rock-It to Stardom’).  
vinil(‘Walking on the Moon’).  
cd( ‘God Bless Tiny Tim’).  
cd(‘Walking on the Moon’).  
cd(‘Autonervous’).  
cd(‘Manuscription’).  
cassette(‘The Human Horn’).  
cassette(‘The Yung & Moore Show’).  
mp3(‘Walkin on the Moon’).  

I need to make a query that will return to me all the albums that were made by only one musician.
Thanks for your help :)

2
You probably need findall/3. Give it a shot and show us what you come up with. - Daniel Lyons
Honestly, I have tried lots of things. As I said I'm a beginner I just started learning prolog last week so I don't know much. I don't know how to use the findall/3 command yet, sorry =/. I Have tried things like album(X,B),album(Y,C), B \= C. But obviously that didnt work xD. - Niammi
You can use Google to find information about findall/3, for example: csupomona.edu/~jrfisher/www/prolog_tutorial/2_12.html. Also, you have to just think logically through the problem. album(X,B), album(Y,C), B\=C. says, An album called B made by X and an album C made by Y where B and C are different doesn't describe the query you said you want. Think about what you're wanting in your query. You can ask: return an album made by musician X (translate into Prolog) and use findall/3 to get all of them. Then check if the list obtained has length of 1. - lurker

2 Answers

2
votes

In the comments you have provided your code album(X,B),album(Y,C), B \= C. Actually, this is not too far away from a correct solution.

A correct solution could be:

one_musician_album(X) :-
    album(A, X), 
    \+ (album(B, X), A \= B).

The meaning of the predicate is: an album X is a "one-musician album" if this album is authored by some musician A and it's not possible to find a different musician B authored the album X.

Test run:

?- one_musician_album(X).
X = 'Walkin on the moon' ;
X = 'The Human Horn' ;
X = 'God Bless Tiny Tim' ;
X = 'Rock-It to Stardom'.

To get all answers you have to type ';' after each answer.

Maybe this is not needed for you, but it's possible to get all answers in a list with findall:

?- findall(X, one_musician_album(X), Albums).
Albums = ['Walkin on the moon', 'The Human Horn', 'God Bless Tiny Tim', 'Rock-It to Stardom'].
2
votes

Here is a generalization, based on 'all solutions' builtin bagof/3.

Note that

?- bagof(A, album(A,T), As).
T = 'Autonervous',
As = ['Jessie Evans', 'Bettina Koster'] ;
T = 'God Bless Tiny Tim',
As = ['Tiny Tim'] 
....

then, restricting the authors (As) to be a list of a single element, we get albums with a single author

?- bagof(A, album(A,T), [A]).
A = 'Tiny Tim',
T = 'God Bless Tiny Tim' ;
...

then, we could use findall/3, as in the good answer by Sergey, or, again, bagof/3, with explicit quantification:

?- bagof(T, A^bagof(A, album(A, T), [A]), Ts).
Ts = ['God Bless Tiny Tim', 'Rock-It to Stardom', 'The Human Horn', 'Walkin on the moon'].