- •Лекція 4.21. Логічні задачі
- •1. Проблема мавпи
- •2. Проблема фермера
- •3. Проблема слідчого
- •4. Поліцейська проблема
- •6. Маскарад
- •7. Таблиця велосипедних змагань
- •8. Студенти на велосипедах
- •11. Проблема зебри.
- •10. Проблема мешканців острова
- •12. Числовий ребус.
- •13. Ігрові програми. Гра "бики й корови" (видатний розум)
- •Висновки.
4. Поліцейська проблема
Jean був убитий у вівторок. Luc, Paul, Alain, Bernard і Louis перебувають під підозрою. Хто є вбивця, якщо прийнято вважати, що:
убивцею є той, хто бажав смерті Jean-a, має зброю й не має алібі на вівторок;
алібі, представлене персоною, що не викликає довіри, не є дійсним;
хтось міг прагнути смерті Jean-a, якщо він був зацікавлений у його смерті або бажав йому помститись;
персона може бути зацікавлена в смерті Jean-a, якщо вона успадковує його власність, якщо винна йому грошей або була помічена на місці злочину.
Анкета дала наступні результати:
В Luc-a є алібі на вівторок, яке надав Bernard;
В Paul-a є алібі на вівторок, яке надав Bernard;
В Louis-a є алібі на вівторок, яке надав Luc;
В Alain-a є алібі на четвер, яке надав Luc;
Alain персона, що не вселяє довіри;
Paul прагнув помститись Jean-у;
Luc прагнув помститись Jean-у;
Bernard є спадкоємцем Jean-a;
Jean є спадкоємцем Louis-a;
Louis винен грошей Jean-у;
Luc винен грошей Jean-у;
Paul бачив Alain-a за скоєнням злочину;
В Luc-а є зброя;
В Louis-а є зброя;
В Alain-а є зброя.
Хто вбивця?
ЛІстинг програми (i):
predicates
person(symbol, symbol).
person(symbol,symbol,symbol).
j_s(symbol).
z_s(symbol).
alibi(symbol).
killer(symbol).
goal
killer(X),
write("KILLER -",X), nl.
clauses
person(alain, prest). % Paul бачив Alain-a за скоєнням
злочину
person(louis,money). % Louis винен грошей Jean-у
person(luc,money). % Luc винен грошей Jean-у
person(paul, mesti). % Paul хотів помститись Jean-у
person(luc, mesti). % Luc хотів помститись Jean-у
person(luc, w). % У Luc-а є зброя
person(alain, w). % У Alain-а є зброя
person(louis, w). % У Louis-а є зброя
person(alain, non). % Alain не вселяє довіри
person(luc,tuesday,bernard). % У Luc-a є алібі на
вівторок, яке надав Bernard
person(paul,tuesday,bernard). % У Paul-a є алібі на
вівторок, яке надав Bernard
person(louis,tuesday,luc). % У Louis-a є алібі на
вівторок, яке надав Luc
person(alain,thursday,luc). % У Alain-a є алібі на
четверг, яке надав Luc
person(jean, hear, louis). % Jean є спадкоємцем Louis-a
person(bernard, hear, jean). % Bernard є
спадкоємцем Jean-a
% Вбивцею Jean-а є його спадкоємець, боржник, той,
% кого бачили на місті злочину, або хотів помститись,
%та одночасно мав зброю і не мав алібі.
killer(X) :- j_s(X), person(X,w), not(alibi(X)).
alibi(X) :- person(X,tuesday,_), person(_,tuesday,X);
not(person(X,non)).
j_s(X):- z_s(X); person(X, mesti).
z_s(X):- person(X, hear, jean).
z_s(X):- person(X,money); person(X, prest).
РЕЗУЛЬТАТ:
KILLER – alain
ЛІстинг програмИ (ii):
domains
name, day = symbol
predicates
person(name).
alibi(name,day,name).
persona_non(name).
mesti(name).
heir(name,name).
money(name).
jean_see(name).
weapon(name).
motive(name).
n_al(name).
killer(name).
goal
killer(X),
write("KILLER -",X), nl.
clauses
person(jean).
person(luc).
person(paul).
person(alain).
person(bernard).
person(louis).
alibi(luc,tuesday,bernard). % У Luc-a є алібі на
вівторок, яке надав Bernard alibi(paul,tuesday,bernard). % У Paul-a є алібі на
вівторок, яке надав Bernard
alibi(louis,tuesday,luc). % У Louis-a є алібі на
вівторок, яке надав Luc
alibi(alain,thursday,luc). % У Alain-a є алібі на
четверг, яке надав Luc
persona_non(alain). % Alain не вселяє довіри
mesti(paul). % Paul хотів помститись Jean-у mesti(luc). % Luc хотів помститись Jean-у
heir(bernard,jean). % Bernard є спадкоємцем Jean-a
heir(jean,louis). % Jean є спадкоємцем Louis-a
paul_see(alain). % Paul бачив Alain-a за скоєнням злочину
money(louis). % Louis винен грошей Jean-у
money(luc). % Luc винен грошей Jean-у
weapon(luc). % У Luc-а є зброя
weapon(louis). % У Louis-а є зброя
weapon(alain). % У Alain-а є зброя
% кілер – той, у кого є мотив (щодо помсти, спадку, %боргу) або свідок злочину, та має зброю і нема алібі
n_al(X) :- not(alibi(X,tuesday,_));
not(alibi(_,tuesday,X));
persona_non(X).
motive(X) :- mesti(X); heir(X,_); jean_see(X); money(X).
killer(X) :- motive(X), weapon(X), n_al(X).
Результат:
KILLER - alain
5. Пасажири – книголюби % Якось в одному купе опинились відомі історик, поет, прозаїк і драматург. % Це були Олексіїв, Борисов, Константинів і Дмитриїв. % Сталось, що кожен з них узяв с собою книгу, написану одним з пасажирів. % Олексіїв і Борисов, кожен дочитав свою книгу, умовились на завтра обмінятись ними. % Поет читав п’єсу. % Прозаїк, дуже молода людина, що видрукував свою першу книгу, казав, що він в житті не читав і не читає нічого з історії. % Борисов купив твір Дмитриєва. % Ніхто з пасажирів не купляв і не читав книгу, написану ним. Що читав кожен з них? Хто ким був? CONSTANTS tab = " " % константа для отступів при виводі результатів Domains жанрКниги, жанрПисателя = symbol фамилияПисателя = symbol возможныеФамилии = фамилияПисателя* пассажир = книголюб(фамилияПисателя,
жанрПисателя,списокКниг) списокПассажиров = пассажир* списокСписковПассажиров = списокПассажиров* книга = книга(фамилияПисателя,жанрКниги) списокКниг = книга* predicates nondeterm возможнаяФамилия(фамилияПисателя) nondeterm пишетВЖанре(жанрПисателя,жанрКниги) nondeterm списокПассажировИКниг(списокПассажиров,
списокКниг) nondeterm одинИз(списокПассажиров,списокСписковПассажиров) nondeterm одинИз(пассажир,списокПассажиров) nondeterm одинИз(книга,списокКниг) nondeterm читал(пассажир,книга) nondeterm взялССобой(пассажир,книга) nondeterm ищемРешение(списокПассажиров) % формування унікального списку рішень і форматний вивід у
вікно програми nondeterm уникальные_решения(списокСписковПассажи-
ров,списокСписковПассажиров,
списокСписковПассажиров) nondeterm списокРешений(списокСписковПассажиров) nondeterm выводРешений() nondeterm выводРешений(списокСписковПассажиров) nondeterm печатьРешенияКтоЧтоЧитал(списокПассажиров) nondeterm печатьРешенияКтоКемБыл(списокПассажиров) CLAUSES одинИз(Х,[Первый|Хвост]):- Х=Первый; одинИз(Х,Хвост). % Якось в одному купе опинились відомі історик, поет, прозаїк
і драматург. пишетВЖанре(историк,история). пишетВЖанре(поэт,стихи). пишетВЖанре(прозаик,проза). пишетВЖанре(драматург,пьеса).
% Це були Олексіїв, Борисов, Константинов і Дмитриїв. возможнаяФамилия(алексеев). возможнаяФамилия(борисов). возможнаяФамилия(конст). возможнаяФамилия(дмитриев). списокПассажировИКниг(Пассажиры,Книги):-
% генерує різні унікальні жанри пишетВЖанре(ЖанрПисателя1,_),
пишетВЖанре(ЖанрПисателя2,_),
пишетВЖанре(ЖанрПисателя3,_),
пишетВЖанре(ЖанрПисателя4,_), % унікальність жанрів not(ЖанрПисателя1=ЖанрПисателя2), not(ЖанрПисателя1=ЖанрПисателя3),
not(ЖанрПисателя2=ЖанрПисателя3), not(ЖанрПисателя1=ЖанрПисателя4),
not(ЖанрПисателя2=ЖанрПисателя4),
not(ЖанрПисателя3=ЖанрПисателя4), % список пасажирів, з різними комбінаціями жанрів Алексеев=книголюб(алексеев, ЖанрПисателя1,[_,_]), Борисов = книголюб(борисов, ЖанрПисателя2 ,[_,_]), Константинов = книголюб(конст,ЖанрПисателя3,[_]), Дмитриев = книголюб(дмитриев, ЖанрПисателя4 ,[_]), % впорядкований список пасажирів Пассажиры=[Алексеев,Борисов,Константинов,Дмитриев], % відповідність жанрів пишетВЖанре(ЖанрПисателя1,ЖанрКниги1), пишетВЖанре(ЖанрПисателя2,ЖанрКниги2), пишетВЖанре(ЖанрПисателя3,ЖанрКниги3), пишетВЖанре(ЖанрПисателя4,ЖанрКниги4), % жанр письменника має відповідати жанру
написаної ним книги К1 = книга(алексеев, ЖанрКниги1), К2 = книга(борисов, ЖанрКниги2), К3 = книга(константинов,ЖанрКниги3), К4 = книга(дмитриев, ЖанрКниги4), % впорядкований список книг Книги = [К1,К2,К3,К4]. % співставляє Книгу з однією з ПрочитанихКниг Пасажира читал(Пассажир,Книга):- Пассажир=книголюб(_,_,ПрочитанныеКниги), одинИз(Книга,ПрочитанныеКниги). взялССобой(Пассажир,Книга):- Пассажир = книголюб(_,_,[Книга|_]), читал(Пассажир,Книга). ищемРешение(Пассажиры):- % Гіпотеза % формуються впорядковані списки, де у пасажирів вказані прізвище і жанр (список прочитаних книг невизначений [_]
або [_,_]) % окремо формується список книг, написаних цими
письменниками списокПассажировИКниг(Пассажиры,Книги), одинИз(Алексеев,Пассажиры), одинИз(Борисов,Пассажиры), одинИз(Константинов,Пассажиры), одинИз(Дмитриев,Пассажиры), Поэт = книголюб(_,поэт,_),
одинИз(Поэт,Пассажиры),
Прозаик = книголюб(_,прозаик,_),
одинИз(Прозаик,Пассажиры), % Сталось, що кожен з них узяв с собою книгу, написану одним з пасажирів. % Перевірка на унікальність книг необхідна тут, оскільки % саме тут говоримо, що кожен пасажир читав одну з книг, %написаних іншими пасажирами одинИз(К1,Книги), одинИз(К2,Книги),not(К1=К2), одинИз(К3,Книги),not(К1=К3),not(К2=К3), одинИз(К4,Книги),not(К1=К4),not(К2=К4),not(К3=К4), Пьеса = книга(_,пьеса), одинИз(Пьеса,Книги), КнигаПоИстории = книга(_,история),
одинИз(КнигаПоИстории,Книги), ПроизведениеДмитриева = книга(дмитриев,_),
одинИз(ПроизведениеДмитриева,Книги), НаписалАлексеев = книга(алексеев,_),
одинИз(НаписалАлексеев,Книги), НаписалБорисов = книга(борисов,_),
одинИз(НаписалБорисов,Книги), НаписалКонстантинов = книга(константинов,_),
одинИз(НаписалКонстантинов,Книги),
НаписалДмитриев = книга(дмитриев,_),
одинИз(НаписалДмитриев,Книги),
% у пасажирів заповнюється список книг, таким чином
формуються всі можливі комбінації рішень. % список пасажирів впорядкований. читал(Алексеев,К1),читал(Борисов,К2),
читал(Константинов,К3),читал(Дмитриев,К4), % ПЕРЕВІРКА ГІПОТЕЗИ % % Олексіїв і Борисов, кожен дочитав свою книгу, умовились на завтра обмінятись ними.
Алексеев = книголюб(алексеев,_,
[КнигаЧиталАлексеев,КнигаЧиталБорисов]), Борисов = книголюб(борисов,_,
[КнигаЧиталБорисов,КнигаЧиталАлексеев]), % Поет читав п’єсу. (В смислі: поет узяв з собою п’єсу, тобто % це була його перша прочитана книга і, можливо, єдина).
% поет узяв з собою п’єсу взялССобой(Поэт,Пьеса), % Прозаїк, дуже молода людина, що видрукував свою першу %книгу, казав, що в житті не читав і не читає нічого з історії. not( читал( Прозаик, КнигаПоИстории)), % Борисов купив твір Дмитриєва. взялССобой(Борисов,ПроизведениеДмитриева), % Дмитриев - не прозаїк, т.к. прозаїк випустив всього одну книгу, а Борисов купив одне з декількох творів Дмириева одинИз(Дмитриев,Пассажиры),
Дмитриев = книголюб(дмитриев,НеПрозаик,_), not(НеПрозаик = "прозаик"), % Ніхто з пасажирів не купляв і не читав книгу,
написану ним самим.
not( читал( Алексеев, НаписалАлексеев)), not( читал( Борисов, НаписалБорисов)), not( читал( Константинов, НаписалКонстантинов)), not( читал( Дмитриев, НаписалДмитриев)). % процедура для фільтрації не унікальних рішень уникальные_решения([],Уникальные_Решения,
Уникальные_Решения). уникальные_решения([Решение|Хвост_Решений],
Уникальные_Решения,Уникальные_Решения_Выход):- not(одинИз(Решение,Уникальные_Решения)), уникальные_решения(Хвост_Решений,
[Решение|Уникальные_Решения],
Уникальные_Решения_Выход). уникальные_решения([Решение|Хвост_Решений],
Уникальные_Решения,Уникальные_Решения_Выход):- одинИз(Решение,Уникальные_Решения), уникальные_решения(Хвост_Решений,
Уникальные_Решения,Уникальные_Решения_Выход). % формує список унікальних рішень списокРешений(Список_Уникальных_Решений):- findall(Пассажиры,ищемРешение(Пассажиры),
Список_Всех_Решений), уникальные_решения(Список_Всех_Решений,[],
Список_Уникальных_Решений). % процедура перебирає список рішень і викликає процедуру вивода кожного рішення на екран в читабельному вигляді выводРешений():- списокРешений(Список_Уникальных_Решений), выводРешений(Список_Уникальных_Решений). выводРешений([]). выводРешений([Решение|ОстальныеРешения]):- nl,write("Вывод решения:"),nl, write(tab,"Кто кем был?"),nl, печатьРешенияКтоКемБыл(Решение), write(tab,"Кто что читал?"),nl, печатьРешенияКтоЧтоЧитал(Решение), выводРешений(ОстальныеРешения). % вивід кожного рішення на екран в читабельному вигляді % відповідь на питання: "Кто кем был?" печатьРешенияКтоКемБыл([]). печатьРешенияКтоКемБыл(Пассажиры):- Пассажиры = [Первый|Остальные], Первый = книголюб(Фамилия,Жанр,_), write(tab,tab,Фамилия, " был ", Жанр,"ом"),nl, печатьРешенияКтоКемБыл(Остальные).
% відповідь на питання: "Кто что читал?" печатьРешенияКтоЧтоЧитал([]). печатьРешенияКтоЧтоЧитал(Пассажиры):- Пассажиры = [Первый|Остальные], Первый = книголюб(Фамилия,_,СписокКниг), write(tab,tab,Фамилия, " читал ", СписокКниг),nl, печатьРешенияКтоЧтоЧитал(Остальные). goal % ВІДПОВІДІ НА ПИТАННЯ % выводРешений().
