310 likes | 480 Views
Програмиране на Пролог. доц. Светла Бойчева Факултет по математика и информатика СУ “Св. Климент Охридски”. Задача ( за изпит).
E N D
Програмиране на Пролог доц. Светла Бойчева Факултет по математика и информатика СУ “Св. Климент Охридски”
Задача (за изпит) • Даден е ориентиран граф. Да се напише предикат, който по зададени два върха X и Y на графа намира (ако съществуват) два "непокриващи се" пътя от X до Y в дадения граф.Два пътя наричаме "непокриващи се", ако нямат обща дъга.
path(X,X,Current,Final):- reverse([X|Current], Final). path(X,Y,Current,Final):- arc(X,Z), \+ member(X,Current), path(Z,Y,[X|Current], Final).
cover(P1,P2):- append(_,[U,W|_],P1), append(_,[U,W|_],P2). solution(X,Y,P1,P2):- path(X,Y,[ ],P1), path(X,Y,[ ],P2), \+ cover(P1,P2).
Приложения на езика Пролог Комбинаторни задачи
Число - Списък • Да се напише предикат, който по зададено естествено число образува списък, който съдържа като елементи последователно цифрите на даденото число. 1234 -> [1, 2, 3, 4] • Да се напише предикат, който по зададен списък от цифри образува число от дадените цифри.
num2list(X,[X]):- X <10,!. num2list(X, Res ):- N is X //10, M is X mod 10, num2list(N,L), append(L,[M],Res).
list2num([X],X):- !. list2num(List, Res):- append(Prev,[LastDigit],List), list2num(Prev,Temp), Res is Temp*10+LastDigit.
Дума - Списък • Да се напише предикат, който по зададена дума образува списък, който съдържа като елементи последователно буквите на дадената дума. • Да се напише предикат, който по зададен списък от букви образува дума от дадените букви.
string2list('',[ ]):- !. string2list(W, List):- name(W, CodeW), codes2letters(CodeW,List). codes2letters([ ],[ ]). codes2letters([C|Rest ],[L|Result]):- name(L, [C]), codes2letters(Rest,Result). list2string([ ], ' '):-!. list2string(List, Result):- codes2letters(CodeW,List), name(Result,CodeW).
Задача (за изпит) • Дадена е база от факти, която съдържа: • person(PersonID,Name,BirthDate,Sex,Address,Phone) • job(PersonID,Company,Address,Position,Salary) • bank_account(PersonID,AccountNumber,Amount,DateIssued, Currency) • BirthDate, DateIssued -> date(Day,Month, Year) • Да се намерят следните данни и резултатите да се запишат в отделни файлове: • Всички хора <име, сума в банковите сметки>, които имат обща сума в банковите сметки, които са открити в последните 5 години, която надвишава доходите им през последните 5 години • Всички хора <име, дата на раждане, сума>, които са под 18 години и имат обща сума в банковите сметки надвишаваща дадено число N • Всички жени <име,дата на раждане, заплата>, които са на възраст между X и Y години и получават заплата по-висока от средната заплата на всички хора на тази възраст
% Подусловие 1 today(date(28,06,2007)). dates_compare(date(D1,M1,Y1), date(D2,M2,Y2), N):- Y2 -Y1 < N,!. dates_compare(date(D1,M1,Y1), date(D2,M2,Y2), N):- Y2 -Y1 =:= N, ( M2 < M1,! ; M2=M1, D2 =< D1) .
person_accounts(PersonID,Name,Suma):- today(TD), findall( X, ( bank_account(PersonID,_,X,D,_), date_compare(D,TD,5) ) , List), summa(List,Suma), person(PersonID,Name,_,_,_,_). summa([X],X). summa([X|L], K):- summa(L,M), K is X+M. person_salary(PersonID,Name,Suma):- findall( X, ( job(PersonID,_,_,_,X), List), summa(List,S1), Suma is 5*12*S1, person(PersonID,Name,_,_,_,_).
task1(List):- findall( Name-Suma, ( person(PersonID,_,_,_,_,_), person_accounts(PersonID,Name,Suma), person_salary(PersonID,Name,Zaplata), Suma > Zaplata), List). write_list([ ]). write_list([X | L]):- write(X), nl, write_list(L). solution_task1(FileName):- open(FileName,write,S), set_output(S), task1(List), write_list(List), close(S).
% Подусловие 2 solution_task2(FileName,N):- open(FileName,write,S), set_output(S), task2(List,N), write_list(List), close(S). task2(List,N):- today(TD), findall( Name-D-Suma, (person(PersonID,Name,D,_,_,_), person_account(PersonID,Name,Suma), dates_compare(D,TD,18), Suma > N ), List).
% Подусловие 3 dates_between(DZ,TD,X,Y):- dates_compare(DZ,TD,Y), \+ dates_compare(DZ,TD,X). persons_between(List,X,Y):- today(TD), findall( PersonID, (person(PersonID,_,D,_,_,_), dates_between(D,TD,X,Y) ), List).
average(List, A):- summa(List,S), length(List,N), A is S/N. average_salary(Group,A):- findall( Z, (member(P,Group), person_salary(P,_,Z)), List), average(List,A).
solution_task3(FileName,X,Y):- open(FileName,write,S), set_output(S), task3(List,X,Y), write_list(List), close(S). task3(List,X,Y):- persons_between(Group,X,Y), average_salary(Group,A), findall( Name-D-Z, ( member(P,Group), person(P,Name,D,female,_,_), person_salary(P,Name,Z), Z > A), List).
Задача (за изпит) • Дадена е база от факти, която съдържа: • person(PersonID,Name,BirthDate,Sex,Address,Phone) • job(PersonID,Company,Address,Position,Salary) • bank_account(PersonID,AccountNumber,Amount,DateIssued, Currency) • BirthDate, DateIssued -> date(Day,Month, Year) • Да се намерят следните данни и резултатите да се запишат в отделни файлове: • Всички хора <име, дата, длъжност>, които работят в дадена фирма на дадена длъжност и са на възраст над X години • Да се напише програма, която за всяка длъжност намира <Длъжност> - <Максимална заплата>/<Фирма1> - <Средна заплата> - <Минимална заплата>/<Фирма2>
task5(Position, Position-Min/C2-A-Max/C1 ):- findall( Salary-Company, job(_,Company,_,Position,Salary),L), max_salary(L,Max-C1), min_salary(L,Min-C2), avg_salary(L,A). max_salary([S-C],S-C). max_salary([S-C|Rest],Max-C1):- max_salary(Rest, T-H), ( S > T, !, Max=S, C1=C ; Max=T, C1=H). min_salary([S-C],S-C). min_salary([S-C|Rest],Min-C1):- min_salary(Rest, T-H), ( S < T, !, Min=S, C1=C ; Min=T, C1=H).
sum_pair([S-C],S). sum_pair([S-C|Rest],Suma):- sum_pair(Rest,S1), Suma is S1 + S. avg_salary(List_of_pairs,A): sum_pair(List_of_pairs, S), length(List_of_pairs,N), A is S/N. all_positions(List):- setof( P, ID^C^A^S^job(ID,C,A,P,S) , List).
solution_task5(FileName):- open(FileName,write,S), set_output(S), task5_final(List), write_list(List), close(S). task5_final(List):- all_positions(AllP), findall( Pairs, ( member(P,AllP), task5(P,Pairs) ), List).
Пермутации / Наредби • Да се напише предикат perm(S,R), който на зададен списък от елементи S да намира негова пермутация (наредба) R. При предудовлетворяване да се намират всички възможни пермутации.
perm([],[]). perm(L,[X|Temp]):- member(X,L), del(X,L,Rest), perm(Rest,Temp). del(X,[X|L],L):-!. del(X,[Y|L1],[Y|L2]):- del(X,L1,L2).
Задача Дадени са данни с имена на хора и политическите партии, на които те се членове. person(Name,PoliticalParty) Да се напише предикат, който намира всички възможни наредби на членовете на дадена партия в нейната изборна бюлетина.
all_buletins(PoliticalParty, Lists):- findall(Name, person(Name,PoliticalParty), List), findall( Order, perm(List,Order), Lists).
Комбинации • Да се напише предикат comb(S,N,K,R), който на зададен списък от елементи(множество) S с N на брой елементи да намира негово подмножество R с K на брой елементи. При предудовлетворяване да се намират всички възможни такива подмножества.
% Вариант 1 comb(_,0,[]). comb(L,K,[X|Temp]):- length(L,N), K =< N, K > 0, K1 is K-1, member(X,L), del(X,L,Rest), comb(Rest,K1,Temp).
% Вариант 2 comb(_,0,[]). comb([X|Rest],K,[X|Temp]):- length([X|Rest],N), K =< N, K > 0, K1 is K-1, comb(Rest,K1,Temp). comb([_|Rest],K,Result):- length(Rest,N), K =< N, K > 0, comb(Rest,K,Result).
all_buletins(PoliticalParty,N, Lists):- findall(Name, person(Name,PoliticalParty), List), findall( Order, comb(List,N,Order), Lists).