Reputation: 137
I know the title of the topic exists here: A prolog program that reflects people sitting at a round table
But I need a different solution, more simple.
So I have this problem where 4 people sit around a square table.
We know their names. And that someone is the orthopedist, someone the dentist, someone the surgeon and someone the pediatrician.
We have a knowledge base that you will see in the code.
And we have to find what is the name of the pediatrician.
My program finds it, but doesn't print all four possible combinations for the list that represents the seats on the table.
table(List):-
length(List,4),
member(convive(argiro,_,female),List),
member(convive(georgia,_,female),List),
member(convive(basilis,_,male),List),
member(convive(dimitris,_,male),List),
left(convive(_,dentist,_),convive(argiro,_,female),List),
oppo(convive(_,surgeon,_),convive(basilis,_,male),List),
next(convive(georgia,_,female),convive(dimitris,_,male),List),
left(convive(_,_,female),convive(_,orthopedist,_),List),
member(convive(_,pediatrecian,_),List).
left(X,Y,ConLs):-append(_,[X,Y|_],ConLs).
left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).
next(X,Y,ConLs):-left(X,Y,ConLs).
next(X,Y,ConLs):-append(_,[Y,X|_],ConLs).
next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).
oppo(X,Y,ConLs):-next(X,Z,ConLs),next(Z,Y,ConLs),X\==Y.
On the terminal I get:
?- table(List),member(convive(Name,pediatrecian,_),List).
List = [convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)], Name = argiro ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)], Name = argiro ;
false.
So as you can see, I get the name, but only the 2 possible lists representing where each person is seated. There should also be:
List = [convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female)]
List = [convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male)]
I have used the lines
left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).
next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).
But, they are not doing anything, if I erase them, I get the same result.
UPDATE
table(List):-
length(List,4),
member(convive(argiro,_,female),List),
member(convive(georgia,_,female),List),
member(convive(basilis,_,male),List),
member(convive(dimitris,_,male),List),
left(convive(_,dentist,_),convive(argiro,_,female),List),
oppo(convive(_,surgeon,_),convive(basilis,_,male),List),
next(convive(georgia,_,female),convive(dimitris,_,male),List),
left(convive(_,_,female),convive(_,orthopedist,_),List),
member(convive(_,pediatrecian,_),List).
left(X,Y,ConLs):-append(_,[X,Y|_],ConLs).
left(X,Y,ConLs):-prefix(X,ConLs),last(ConLs,Y).
next(X,Y,ConLs):-left(X,Y,ConLs);left(Y,X,ConLs).
%next(X,Y,ConLs):-append(_,[Y,X|_],ConLs).
next(X,Y,ConLs):-prefix(Y,ConLs),last(ConLs,X).
%oppo(X,Y,ConLs):-next(X,Z,ConLs),next(Z,Y,ConLs),X\==Y.
oppo(X,Y,[X,_,Y,_]).
oppo(X,Y,[Y,_,X,_]).
oppo(X,Y,[_,X,_,Y]).
oppo(X,Y,[_,Y,_,X]).
So, oppo/3 seems to be working fine on the given lists
?- table(List), oppo(convive(argiro,pediatrecian,female),Name,List).
List = [convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)],
Name = convive(dimitris, orthopedist, male) ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = convive(dimitris, orthopedist, male) ;
false.
left/3 seems to be doing the same thing that I'm trying to solve in the first place, it works in the list where argiro is number 2 and georgia is 3 which is a simple case, but in the second list that you can see above in oppo/3 results, where argiro is number 4 and georgia is number 1, it should see that georgia is again on the left of argiro but doesn't.
?- table(List), left(convive(argiro,pediatrecian,female),Name,List).
List = [convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)],
Name = convive(georgia, surgeon, female) ;
false.
Now next/3 returns some pretty disturbing results. I don't know what to make of this, I'm a newbie in Prolog. Some are okay, but some seem to be taking whole arrays as results, some say List = Name.
The first three results are ok, and the fourth is doing the same as left/3, it can't see that the first one in the list is next to the last one so it returns an empty array.
What is happening here?
?- table(List), next(convive(argiro,pediatrecian,female),Name,List).
List = [convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)],
Name = convive(georgia, surgeon, female) ;
List = [convive(basilis, dentist, male), convive(argiro, pediatrecian, female), convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)],
Name = convive(basilis, dentist, male) ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = convive(basilis, dentist, male) ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female)] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male)] ;
List = Name,
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female)] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male)] ;
List = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)],
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male)] ;
List = Name,
Name = [convive(georgia, surgeon, female), convive(dimitris, orthopedist, male), convive(basilis, dentist, male), convive(argiro, pediatrecian, female)] ;
false.
UPDATE
So I learned that prefix/2 works with strings, for example,
prefix(x,[x,y,z]).
returns false.
That's why it's not working, and that explains the results in next/3, but still my problem isn't solved.
Any other way to make left and next work with the first and last part of the list?
Upvotes: 2
Views: 356
Reputation: 71065
I bet the culprit is \==
in oppo
, because these predicates are used here in generative fashion. Try to get rid of it. Just hand-coding the four possibilities is enough - your lists are of fixed length and very short, after all:
oppo(X,Y,[X,_,Y,_]).
.....
next/3
is easier / clearer if coded as a disjunction of two calls to left/3
.
For left/3
itself, you could also form a circle from your ConLs
by
circle_up(Ls,Circle):- head(A,Ls), append(Ls,[A],Circle).
and use Circle
in one simple call to append
to complete the definition of left/3
. This assumes the definition
head(A,L):- L=[A|_].
Upvotes: 0