Маскарад


Одного разу четверо хлопців вирішили, що на свято Хеллоуин цього року всі вони прийдуть у різних костюмах і будуть разом улаштовувати жарту й розіграші. Один з них прийшов у костюмі кістяка, інший – пірата, хтось одягся відьмою, а хтось – Робін Гудом.

Із наступних тверджень треба визначити прізвище кожного із хлопців (прізвище одного з них Финли) і хто в який костюм був одягнений.


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),

% жоден з них не є відьма або пірат