Требуется разработать алгоритм решения логической задачи «Маскарадные костюмы»:
Однажды четверо ребят решили, что на праздник Хеллоуин в этом году все они придут в разных костюмах и будут вместе устраивать шутки и розыгрыши. Один из них пришел в костюме скелета, другой – пирата, кто-то оделся ведьмой, а кто-то – Робин Гудом.
Из сделанных ниже утверждений определите фамилию каждого из ребят (фамилия одного из них Финли) и кто в какой костюм был одет.
1) Джимми и Молли – брат и сестра, но ни тот, ни другой не были одеты ни в костюм ведьмы, ни в костюм пирата.
2) Дом мальчика по фамилии Смит находится напротив дома Джимми и Молли, но и он не надел костюм ведьмы.
3) Билли живет за несколько домов от них, но пиратом был одет не он.
4) Костюм-скелет оказался «гвоздем программы» карнавала. Но носил его не Сэм.
5) Один из Диксонов был в костюме Робин Гуда.
Исходный код программы на Visual Prolog:
DOMAINS
rstring=reference string %eto ya sama ne znayu zachem, no bez etogo ne kompilit
%no mozgete poprobovat steret eto i vezde dalshe zamenit rstring na 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 standartnii predicat,proveryayushii yavlyaetsya li element chlenom spiska
%Kogda pishetsya [H|Tail], to H - eto "golova" spiska, te ego pervii element, a
%Tail - "hvost" vse ostalnie. Kogda pishetsya _, to eto bezimyanaya peremennaya,
%te ee znachenie ne vazgno i mi k nei ne budem v dalneishem obrashatsya
member(H,[H|_]). %Esli element golova, to on clen spiska
member(H,[_|Tail]):-member(H,Tail). %Esli element clen hvosta spiska, to on i clen vsego spiska
%append standartnii predicat sliyaniya dvuh spiskov
append([],B,B). %sliyanii pustogo spiska so vtorum budet vtoroi spisok
append([H|Tail],B,[H|NewTail]):-append(Tail,B,NewTail). %sliyanie spiska so vtorum spiskom
%budet golova pervogo spiska b rezultat sliyaniya hvosta pervogo spiska so vtorum spiskom
names(["Djimmi","Molli","Billi","Sem"]). %predicat, generyashii spisok imen
%predicat vstavki elementa Y na lyuboe mesto spiska XZ. append(X,Z,XZ) oznachaet,
%chto prolog sam nahodit vse vozmozgnii znacheniya X i Z takie, chto rezultatom ih
%sliyaniya budet spisok XZ. Te mi razdelyaem XZ na nachalo(X) i konec(Z), kotorue
%mogut bit i pustimi, slivaem nachalo c elementov Y, a zatem poluchivsheesya s koncom
insert(Y,XZ,XYZ):-append(X,Z,XZ),append(X,[Y],Temp),append(Temp,Z,XYZ).
%predicat perestanovki elementov spiska
permute([],[]).%perestanovkoi pustogo spiska budet tolko pustoi spisok
permute([H|Tail],Ans):-permute(Tail,Temp),insert(H,Temp,Ans). %perestanovkoi nepustogo spiska
%budet perestanovka ego hvosta, a zatem vstavka tuda golovi na lyuboe mesto
%generit spisok kostyumov
suits(List):-permute([skelet,pirat,vedma,robingud],List).
%generit spisok familii. Tut permute nelzya, poskolku dve odinakovae familii
%i kazgdaya perestanovka povtoryalas bi dva raza
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]), %tut mi vse sgenerili, dalshe budem proveryat podhodit li
member(kid("Djimmi",SurnameDjim,_),Solve), member(kid("Molli",SurnameDjim,_),Solve),%u Djimmi i Molli odinakovaya familiya
not(member(kid(_,SurnameDjim,vedma),Solve)), not(member(kid(_,SurnameDjim,pirat),Solve)),%ni tot ni drugoi ne vedma i ne pirat
not(member(kid("Djimmi","Smit",_),Solve)), not(member(kid(_,"Smit",vedma),Solve)),%u Djimmi familiya ne Smith, i Smith ne vedma
not(member(kid("Billi","Smit",_),Solve)), not(member(kid("Billi",_,pirat),Solve)),%u Billi familiya ne Smith i on ne pirat
not(member(kid("Sem",_,skelet),Solve)),%sem ne skelet
member(kid(_,"Dikson",robingud),Solve).%odin iz Diksonov robin-gud
%prosto krasivo vuvodit reshenie
writeSolve([]).
writeSolve([kid(Name,Surname,Suit)|Tail]):-write(Name," ",Surname," - ",Suit),nl,writeSolve(Tail).
%nahodit reshenie, vuvodit ego. fail chto bu nahodilis vse resheniya
go:-find(Solve), writeSolve(Solve),nl,nl,nl,fail.
GOAL
go.
|