There is a logical problem: four friends: Ivan, Petr, Mikhail, Sergey spent their time in different ways: two were playing chess, one read books, one watched TV. Find who does what if Sergey does not play chess and Petr did not watch TV.
Here is my solution:
PREDICATES
question(string,string,string,string)
friend(string)
readBook(string)
watchTV(string)
playsChess(string, string)
CLAUSES
friend(ivan).
friend(petr).
friend(mikhail).
friend(sergey).
readBook(X):-
friend(X).
watchTV(X):-
friend(X),
X<>"petr".
playsChess(X,Y):-
friend(X),
friend(Y),
X<>Y,
X<>"sergey",
Y<>"sergey".
question(A,B,C,D):-
friend(A),
friend(B),
friend(C),
friend(D),
playsChess(A,B),
readBook(C),
watchTV(D),
A<>B, A<>C, A<>D,
B<>C, B<>D,
C<>D.
GOAL
question(A,B,C,D).
I have the following solution:
A=ivan, B=petr, C=mikhail, D=sergey (1)
A=ivan, B=petr, C=sergey, D=mikhail (2)
A=ivan, B=mikhail, C=petr, D=sergey (3)
A=petr, B=ivan, C=mikhail, D=sergey (4)
A=petr, B=ivan, C=sergey, D=mikhail (5)
A=petr, B=mikhail, C=ivan, D=sergey (6)
A=petr, B=mikhail, C=sergey, D=ivan (7)
A=mikhail, B=ivan, C=petr, D=sergey (8)
A=mikhail, B=petr, C=ivan, D=sergey (9)
A=mikhail, B=petr, C=sergey, D=ivan (10)
10 Solutions
But some lines are redundant since they are combined A and B. For example lines (1) and (4) (A=ivan, B=petr and A=petr, B=ivan).
I tried to use !
here:
playsChess(X,Y):-!,
friend(X),
friend(Y),
X<>Y,
X<>"sergey",
Y<>"sergey".
but it has no effect. So the question is: how can I get rid of excess solution results?
The simplest way to solve the problem would be to constrain A
and B
further and force one to be "greater" than the other. I'm not sure exactly if this is the syntax in Visual Prolog, but try this. Note the use of A > B
instead of A <> B
.
question(A,B,C,D):-
friend(A),
friend(B),
friend(C),
friend(D),
playsChess(A,B),
readBook(C),
watchTV(D),
A > B, A<>C, A<>D,
B<>C, B<>D,
C<>D.
By constraining with >
instead of <>
you will ensure that you won't have symmetrical cases. For example, a > b
is false, but a < b
is true. However, both a <> b
and b <> a
are true, so the <>
gives both a, b
and b, a
.
Your cut (!
) did nothing because when you use it on a predicate that has only one clause like this:
my_predicate(...) :- !, subqueries ...
It just tells Prolog not to backtrack beyond the beginning of the first subquery. Since there are no other my_predicate
clauses to backtrack to anyway, it has no effect.