Пролог логическое задание
Есть логическая проблема: четверо друзей: Иван, Петр, Михаил, Сергей проводили время по-разному: двое играли в шахматы, один читал книги, один смотрел телевизор. Найдите, кто что делает, если Сергей не играет в шахматы, а Петр не смотрит телевизор.
Вот мое решение:
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).
У меня есть следующее решение:
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
Но некоторые строки являются избыточными, поскольку они объединены A и B. Например, строки (1) и (4) (A=ivan, B=petr и A=petr, B=ivan). Я пытался использовать !
Вот:
playsChess(X,Y):-!,
friend(X),
friend(Y),
X<>Y,
X<>"sergey",
Y<>"sergey".
но это не имеет никакого эффекта. Итак, вопрос: как я могу избавиться от лишних результатов решения?
2 ответа
Простейшим способом решения проблемы было бы ограничение A
а также B
дальше и заставить одного быть "больше" другого. Я не уверен, точно ли это синтаксис в Visual Prolog, но попробуйте это. Обратите внимание на использование A > B
вместо 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.
Ограничивая >
вместо <>
Вы убедитесь, что у вас не будет симметричных случаев. Например, a > b
ложно, но a < b
правда. Тем не менее, оба a <> b
а также b <> a
верно, поэтому <>
дает оба a, b
а также b, a
,
Ваш разрез (!
) ничего не сделал, потому что когда вы используете его в предикате, который имеет только одно предложение, подобное этому:
my_predicate(...) :- !, subqueries ...
Он просто говорит Прологу не отступать после начала первого подзапроса. Так как других нет my_predicate
пункты, чтобы вернуться в любом случае, это не имеет никакого эффекта.
Подумайте об использовании переменной, которую вы вводите для каждого друга, чтобы напрямую представить деятельность, соответствующую этому человеку:
friends([ivan=Ivan,petr=Petr,mikhail=Mikhail,sergey=Sergey]) :-
Fs0 = [Ivan,Petr,Mikhail,Sergey],
dif(Sergey, chess),
dif(Petr, tv),
select(books, Fs0, Fs1),
select(tv, Fs1, [chess,chess]).
Пример запроса и его результат:
?- friends(Fs).
Fs = [ivan=books, petr=chess, mikhail=chess, sergey=tv] ;
Fs = [ivan=chess, petr=books, mikhail=chess, sergey=tv] ;
Fs = [ivan=chess, petr=chess, mikhail=books, sergey=tv] ;
Fs = [ivan=tv, petr=chess, mikhail=chess, sergey=books] ;
Fs = [ivan=chess, petr=chess, mikhail=tv, sergey=books] ;
false.