0

I have a school project where I have to work with Prolog. This is all new to me, so I'm having some problems.

I have a list like this:

List = [(_,_,_),(_,_,_),(_,_,_)]

I'm supposed to receive from the input information about each member, through several predicates that I must create.

One of them is of the type:

predicate(M1,M2,M3, List)

and it says that M1 is either M2 or M3, but not both. For example,

predicate((_,a,_),(2,_,_),(3,_,_),List)

states that the member with 'a', has either 2 or 3 in the first field.

I've been trying all night but can't come up with a solution. I believe I have to use the unification, but don't know how to do it.

I've tried this:

predicate(M1,M2,M3,[_]) :- (M1=M2), not(M1=M3).
predicate(M1,M2,M3,[_]) :- (M1=M3), not(M1=M2).

This may look ridiculous, but as I said, Prolog is completely new to me and I can't quite grasp its functioning.

Any hint is appreciated. Thanks!

EDIT:

Example:

person(name,age,job).
List = [(einstein,_,_),_,_].

So now I have a list List of 3 people, with einstein in the first position.

predicate = ((einstein,_,_),(_,87,_),(_,23,_), List).

List = [(einstein,87,_),_,_)];
List = [(einstein,23,_),_,_)].

These above are the 2 acceptable lists after applying the predicate.

It should be a simple problem but I can't figure it out.

Thanks!

false
  • 10,264
  • 13
  • 101
  • 209
bex91
  • 123
  • 8
  • Well, I tried to explain it in the question. Not sure what else to add. The predicate is supposed to receive properties about 3 members of the list meaning that the first will be the same as one of the other two. (hifen is the underscore, can't write it here) predicate((einstein,-,-),(-,32,-),(-,45,-),List) means that einstein will either be 32 or 45 years old, for example. – bex91 May 17 '13 at 05:25
  • edited :) Hope it's clearer now. – bex91 May 17 '13 at 05:46
  • I'm sorry I didn't see that question. I searched but didn't notice it. I believe it applies to my problem. I'll try to take the most out of it. Thanks! – bex91 May 17 '13 at 05:55
  • no problem, it's pretty standard around here… – Daniel Lyons May 17 '13 at 05:57

3 Answers3

1

I guess that you should bind elements in List:

predicate(M1, M2, M3, [M1, M2, M3]) :-
    M1 = M2, M1 \= M3
  ; M1 = M3, M1 \= M2.

EDIT: after comments

predicate(M1, M2, M3, List) :-
    member(M1, List),
    ( M1 = M2, M1 \= M3 ; M1 = M3, M1 \= M2 ).

Member/2 it's the most basic relation in Prolog between a list and its elements. Here it shows the ability of the underlying engine to bind variables while searching for a solution.

Your data yields

?- predicate((einstein,_,_),(_,87,_),(_,23,_), [E]).
E = (einstein, 87, _G3908) ;
E = (einstein, 23, _G3908).
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Thanks for your help, but I don't think I've explained myself properly. Sorry. M2 and M3 are supposed to be outside of the list where M1 is. I've edited the question, and I think it's understandable now :D – bex91 May 17 '13 at 05:47
  • Thanks again. I've tested this code and the output still isn't perfect, but it's getting close. I got this: E = [ (einstein, 87, _G824), _G832, _G835] ; E = [ (einstein, 23, _G824), _G832, _G835] ; E = [ (einstein, _G823, _G824), (einstein, 87, _G842), _G835] ; E = [ (einstein, _G823, _G824), (einstein, 23, _G842), _G835] ; E = [ (einstein, _G823, _G824), _G832, (einstein, 87, _G842)] ; E = [ (einstein, _G823, _G824), _G832, (einstein, 23, _G842)] ; – bex91 May 17 '13 at 06:20
  • Sorry, I don't know how to format the text properly in here :( The problem is that it's spreading einstein to the rest of the list. Is there any way to avoid this? – bex91 May 17 '13 at 06:24
  • 1
    place a cut after your solution, that will *commit* to choices done. Or use once/1, can be clearer. But generally you should don't care about that, to get benefits from declarativeness of Prolog. If applicable, of course, it depends from context. – CapelliC May 17 '13 at 06:26
1

I'd write it like this:

predicate(M1,M2,M3,L):- member(M1,L),member(M1,[M2,M3]).

you say "it says that M1 is either M2 or M3, but not both" but I think that's your responsibility, as a caller of this predicate. If you've supplied equal M2 and M3, evidently you wanted them equal. And if you've supplied them different, well, that's what they are.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Hey, thanks for the feedback. I can't quite understand what you mean though. Suppose I get this input: predicate((einstein,-,-),(-,32,-),(-,-,swimmer),L). It states that einstein is either 32 or a swimmer, but not both. Having M1=M2, M1=M3 would be true, which doesn't work accordingly to my predicate. – bex91 May 17 '13 at 18:40
  • @bex you do not explain/show a sample usage call. Maybe I misunderstood you. – Will Ness May 17 '13 at 18:48
0

Prolog is very different from other programming languages. Your attempt is not unreasonable, but would read better as:

predicate(M1,M1,M3,[_]) :- M1 \= M3.
predicate(M1,M2,M1,[_]) :- M1 \= M2.

This says the same thing, really, but this version draws attention to the fact that we're not doing anything with the fourth argument, which in this formulation could be any single-element list. Odds are good this isn't what you meant.

Daniel Lyons
  • 22,421
  • 2
  • 50
  • 77