- •Лекція 4.21. Логічні задачі
- •1. Проблема мавпи
- •2. Проблема фермера
- •3. Проблема слідчого
- •4. Поліцейська проблема
- •6. Маскарад
- •7. Таблиця велосипедних змагань
- •8. Студенти на велосипедах
- •11. Проблема зебри.
- •10. Проблема мешканців острова
- •12. Числовий ребус.
- •13. Ігрові програми. Гра "бики й корови" (видатний розум)
- •Висновки.
6. Маскарад
Одного разу четверо хлопців вирішили, що на свято Хеллоуин цього року всі вони прийдуть у різних костюмах і будуть разом улаштовувати жарту й розіграші. Один з них прийшов у костюмі кістяка, інший – пірата, хтось одягся відьмою, а хтось – Робін Гудом.
Із наступних тверджень треба визначити прізвище кожного із хлопців (прізвище одного з них Финли) і хто в який костюм був одягнений.
1) Джимми й Молли – брат і сестра, але ні той, ні інший не були одягнені ні в костюм відьми, ні в костюм пірата.
2) Будинок хлопчика на прізвище Смит перебуває напроти будинку Джимми й Молли, але й він не надяг костюм відьми. 3) Біллі живе за кілька будинків від них, але піратом був одягнений не він.
4) Костюм-Кістяк виявився «цвяхом програми» карнавалу. Але носив його не Сем.
5) Один з Диксонов був у костюмі Робін Гуда.
Вихідний код програми на Visual Prolog:
DOMAINS rstring=reference string
kid=kid(rstring,rstring,rstring) %tip-kid(imya,familiya,kostyum) kids=kid* %tip-spisok detei slist=rstring* %tip-spisok strok PREDICATES nondeterm member(kid,kids) nondeterm append(slist,slist,slist) names(slist) nondeterm suits(slist) %список костюмів nondeterm surnames(slist) % список прізвищ
nondeterm insert(rstring,slist,slist) nondeterm permute(slist,slist) nondeterm find(kids) nondeterm writeSolve(kids) nondeterm go CLAUSES %member – предикат перевірки, чи входить елемент у список
member(H,[H|_]). %Якщо елемент є головою списку,
%то він входить у список
member(H,[_|Tail]):-member(H,Tail). %Якщо елемент входить
у хвіст списку, то він входить і у список
%вбудований предикат злиття двох списків
append([],B,B). %злиття порожнього списку із другим
% дає другий список append([H|Tail],B,[H|NewTail]):-append(Tail,B,NewTail).
%злиття списку із другим списком буде: голова
% першого списку стає головою результату,
% чиїм хвостом є результат злиття хвоста
% першого списку із другим списком
names(["Djimmi","Molli","Billi","Sem"]). % генерує список
імен
%предикат вставки елемента Y на довільне місце списка XZ:
%XZ поділяють на початок (X) i кінець (Z), які можуть бути і
% порожніми, потім зливають початок (X) з елементом Y та
% отримане з кінцем (Z) insert(Y,XZ,XYZ):- append(X,Z,XZ),append(X,[Y],Temp),
append(Temp,Z,XYZ). %append(X,Z,XZ) означає, що
% пролог сам відшукує всі можливі
% значення X i Z такі, що результатом
% їхнього злиття буде список XZ.
%перестановка елементів списку permute([],[]).
permute([H|Tail],Ans):-
permute(Tail,Temp),insert(H,Temp,Ans). %перестановкою
% непорожнього списку буде перестановка його
% хвоста та вставка туди голови на довільне місце
%породження списку костюмів suits(List):-permute([skelet,pirat,vedma,robingud],List). %породження списку призвищ
surnames(List):-insert("Smit",["Finli","Finli"],Temp),
insert("Dikson",Temp,List). surnames(List):-insert("Finli",["Smit","Smit"],Temp),
insert("Dikson",Temp,List). surnames(List):-insert("Smit",["Dikson","Dikson"],Temp),
insert("Finli",Temp,List). find(Solve):-Solve=[kid(N1,S1,K1),kid(N2,S2,K2),
kid(N3,S3,K3),kid(N4,S4,K4)],
names([N1,N2,N3,N4]), surnames([S1,S2,S3,S4]),
suits([K1,K2,K3,K4]), % генеруються варіанти імен,
прізвищ, костюмів дітей, далі перевірка, чи
% однакові прізвища у Djimmi i Molli
member(kid("Djimmi",SurnameDjim,_),Solve),
member(kid("Molli",SurnameDjim,_),Solve),
% жоден з них не є відьма або пірат
not(member(kid(_,SurnameDjim,vedma),Solve)),
not(member(kid(_,SurnameDjim,pirat),Solve)),
%у Djimmi призвіще не Smith, і Smith – не відьма
not(member(kid("Djimmi","Smit",_),Solve)),
not(member(kid(_,"Smit",vedma),Solve)),
%у Billi призвіще не Smith і він не пірат
not(member(kid("Billi","Smit",_),Solve)),
not(member(kid("Billi",_,pirat),Solve)),
% Sem не кістяк
not(member(kid("Sem",_,skelet),Solve)),
%один з Diksonov є робінгуд
member(kid(_,"Dikson",robingud),Solve).
%друк рішення writeSolve([]). writeSolve([kid(Name,Surname,Suit)|Tail]):-
write(Name," ",Surname," - ",Suit),nl,writeSolve(Tail). go:-find(Solve), writeSolve(Solve),nl,nl,nl,fail. %відшукує
%рішення, друкує його. fail для
%відкату задля пошуку всіх рішень GOAL go.
