Sunteți pe pagina 1din 30

Universitatea Bucureti Departamentul de Tehnologii Specializarea Tehnologia Informaiei Zi

Coordonator: Prof. Univ. Dr. Marin Vlada Student:

Bucureti 2011
1

Cuprins

1.

Probleme de dificultate mare...pag. 3 1.1. Sudoku.....................................................................pag. 3 1.2. Testul de inteligen al lui Einstein...........................pag. 6 1.3. Problema celor N-Dame...........................................pag. 10 1.4. Misionari i canibali.................................................pag. 12 Probleme de dificultate medie.....pag. 15 2.1. Relaii de familie.........................................................pag. 15 2.2. Operaii cu liste...........................................................pag. 18 2.3 Problema celor 4 specialiti........................................pag. 20 2.4 Maimua i banana.....................................................pag. 22 Probleme de dificultate redus....pag. 24 3.1 irul lui Fibonacci...................................................pag. 24 3.2 Problema turnurilor din Hanoi................................pag. 25 3.3 Minimul, maximul, c.m.m.d.c. a 2 numere i maximul i minimul

2.

3.

elementelor unei liste....................................................................pag. 26 3.4 Derivare simbolic...................................................pag. 27

1. Probleme de dificultate mare


1.1 Sudoku
Jocul Sudoku reprezint un puzzle bazat pe logic ce const n plasarea combinatoric a numerelor. Obiectivul l reprezint completarea unei grile 9 x 9 cu cifre, astfel nct toate fiecare coloan, fiecare rnd i fiecare sub-gril de 3 x 3 (ce compune grila) s conin cifre de la 1 la 9. Fiecare variant ofer o gril parial completat ce implic, n mod normal, o singur soluie. Orice puzzle completat reprezint ntotdeauna un tip de ptrat Latin (n combinatoric acest termen desemnnd un ptrat n x n, compus din n litere diferite, fiecare aprnd o singur pe un rnd i o singur dat pe o coloan) cu constrngeri adiionale pe sub-grile. Cea mai popular i des ntlnit variant de Sudoku o reprezint cea cu o gril de 9 x 9, ce implic urmtoarele reguli: - aceeai cifr de la 1 la 9 nu poate aprea de 2 ori pe acelai rnd - aceeai cifr de la 1 la 9 nu poate aprea de 2 ori pe aceeai coloan - aceeai cifr de la 1 la 9 nu poate aprea de 2 ori n aceeai sub-gril de 3 x 3

Enun:
S se proiecteze un cod surs n SWI-Prolog care s rezolve jocul Sudoku. Datele caracteristice variantei jocului s fie introduse n codul surs, iar soluia s fie furnizat prin interogare.

Codul surs:
:- use_module(library(clpfd)). % utilizarea librariei clpfd ce contine constrangeri logice peste domenii finite % prin intermediul acesteia putem utiliza functia labeling(+options,+vars) sudoku :L=[ _,_,3, _,_,_, _,1,7, _,_,_, _,_,8, _,_,_, _,_,_, 6,3,_, _,9,_, _,1,_, 3,_,_, 5,_,_, _,7,_, 4,_,5, _,9,_, _,_,8, _,_,9, _,4,_,

_,2,_, _,4,6, _,_,_, _,_,_, 2,_,_, _,_,_, 1,7,_, _,_,_, 4,_,_ ], % datele de intrare conform variantei de joc % pot fi modificate dupa preferinte sudoku(L). 3

sudoku([A1,A2,A3, A4,A5,A6, A7,A8,A9, B1,B2,B3, B4,B5,B6, B7,B8,B9, C1,C2,C3, C4,C5,C6, C7,C8,C9, D1,D2,D3, D4,D5,D6, D7,D8,D9, E1,E2,E3, E4,E5,E6, E7,E8,E9, F1,F2,F3, F4,F5,F6, F7,F8,F9, G1,G2,G3, G4,G5,G6, G7,G8,G9, H1,H2,H3, H4,H5,H6, H7,H8,H9, I1,I2,I3, I4,I5,I6, I7,I8,I9]) :% daca toate randurile sunt valide valid([A1,A2,A3,A4,A5,A6,A7,A8,A9]), valid([B1,B2,B3,B4,B5,B6,B7,B8,B9]), valid([C1,C2,C3,C4,C5,C6,C7,C8,C9]), valid([D1,D2,D3,D4,D5,D6,D7,D8,D9]), valid([E1,E2,E3,E4,E5,E6,E7,E8,E9]), valid([F1,F2,F3,F4,F5,F6,F7,F8,F9]), valid([G1,G2,G3,G4,G5,G6,G7,G8,G9]), valid([H1,H2,H3,H4,H5,H6,H7,H8,H9]), valid([I1,I2,I3,I4,I5,I6,I7,I8,I9]), % si daca toate coloanele sunt valide valid([A1,B1,C1,D1,E1,F1,G1,H1,I1]), valid([A2,B2,C2,D2,E2,F2,G2,H2,I2]), valid([A3,B3,C3,D3,E3,F3,G3,H3,I3]), valid([A4,B4,C4,D4,E4,F4,G4,H4,I4]), valid([A5,B5,C5,D5,E5,F5,G5,H5,I5]), valid([A6,B6,C6,D6,E6,F6,G6,H6,I6]), valid([A7,B7,C7,D7,E7,F7,G7,H7,I7]), valid([A8,B8,C8,D8,E8,F8,G8,H8,I8]), valid([A9,B9,C9,D9,E9,F9,G9,H9,I9]), % si daca toate sub-grilele 3x3 sunt valide valid([A1,A2,A3,B1,B2,B3,C1,C2,C3]), valid([A4,A5,A6,B4,B5,B6,C4,C5,C6]), valid([A7,A8,A9,B7,B8,B9,C7,C8,C9]), valid([D1,D2,D3,E1,E2,E3,F1,F2,F3]), valid([D4,D5,D6,E4,E5,E6,F4,F5,F6]), valid([D7,D8,D9,E7,E8,E9,F7,F8,F9]), valid([G1,G2,G3,H1,H2,H3,I1,I2,I3]), valid([G4,G5,G6,H4,H5,H6,I4,I5,I6]), valid([G7,G8,G9,H7,H8,H9,I7,I8,I9]),

% si daca Labeling(+Options, +Vars) % Labeling inseamna incercarea sistematica a valorilor pentru variabilele unui domeniu finit Vars pana la epuizare. % Options reprezinta o lista de optiuni ce ii permite utilizatorului sa controleze procesul de cautare. % ff: First fail - urmatoarea etichetata este cea mai din stanga variabila cu domeniul cel mai mic, pentru detectarea vremelnica a infezabilitatii. labeling([ff],[A1,A2,A3,A4,A5,A6,A7,A8,A9, B1,B2,B3,B4,B5,B6,B7,B8,B9, C1,C2,C3,C4,C5,C6,C7,C8,C9, D1,D2,D3,D4,D5,D6,D7,D8,D9, E1,E2,E3,E4,E5,E6,E7,E8,E9, F1,F2,F3,F4,F5,F6,F7,F8,F9, G1,G2,G3,G4,G5,G6,G7,G8,G9, H1,H2,H3,H4,H5,H6,H7,H8,H9, I1,I2,I3,I4,I5,I6,I7,I8,I9]), % si daca printam rezultatul print_sudoku([A1,A2,A3,A4,A5,A6,A7,A8,A9, B1,B2,B3,B4,B5,B6,B7,B8,B9, C1,C2,C3,C4,C5,C6,C7,C8,C9, D1,D2,D3,D4,D5,D6,D7,D8,D9, E1,E2,E3,E4,E5,E6,E7,E8,E9, F1,F2,F3,F4,F5,F6,F7,F8,F9, G1,G2,G3,G4,G5,G6,G7,G8,G9, H1,H2,H3,H4,H5,H6,H7,H8,H9, I1,I2,I3,I4,I5,I6,I7,I8,I9]). % atunci sudoku (solutia) % testeaza daca valorile apartin intervalului [1,9] si daca nu se repeta valid(L) :length(L,9), L ins 1..9, all_different(L). print_sudoku([]). print_sudoku([R1,R2,R3,R4,R5,R6,R7,R8,R9|R_urmator]) :format('~d ~d ~d | ~d ~d ~d | ~d ~d ~d \n',[R1,R2,R3,R4,R5,R6,R7,R8,R9]), print_sudoku(R_urmator). % specificarea formatului de printare

Interogare:

1.2 Testul de inteligen al lui Einstein


Einstein a inventat aceast problem n sec. XIX. Enunul su: a. Pe o strad se afl 5 case, vopsite n 5 culori distincte; b. n fiecare cas triete o persoan cu o naionalitate diferit de cea a celorlali; c. Aceti 5 proprietari beau fiecare buturi distincte, fumeaz mrci de igar diferite i dein animale diferite. ntrebarea: Cine deine acvariul cu peti? Indicii: a. Englezul triete n casa roie. b. Suedezul deine cini. c. Danezul bea ceai. d. Casa verde este lng i la stnga casei albe. e. Proprietarul casei verzi bea cafea. f. Persoana ce fumeaz Pall Mall deine psri. g. Proprietarul casei galbene fumeaz Dunhill. h. Proprietarul casei din centru bea lapte. i. Norvegianul triete n prima cas. j. Persoana ce fumeaz Blends triete lng cel ce deine pisici. 6

k. Persoana ce deine cai triete lng cea ce fumeaz Dunhill. l. Persoana ce fumeaz Blue Master bea bere. m. Germanul fumeaz Prince. n. Norvegianul triete lng casa albastr. o. Persoana ce fumeaz Blends are un vecin ce bea ap.

Enun:
S se proiecteze un cod surs n SWI-Prolog care s rezolve problema lui Einstein.

Codul surs:
% In primul rand, cream o lista ce sa contina toata informatia despre o persoana. Positia N din lista indica pozitia casei pe strada. % Primul predicat se sfarseste cand indexul e 0 si lista e goala. Al doilea creeaza o lista recursiva cu N elemente. persoane(0, []) :- !. persoane(N, [(_Persoana,_Culoare,_Bautura,_Fumeaza,_Animal)|T]) :- N1 is N-1, persoane(N1,T). % Am utilizat un predicat pentru a obtine al N-lea element daca acesta corespunde unei informatii a listei recursive. % Primul predicat este utilizat pentru a se opri cand suntem la elementul bun. Al doilea itereaza pana cand un element bun este gasit. persoana(1, [H|_], H) :- !. persoana(N, [_|T], R) :- N1 is N-1, persoana(N1, T, R). % Am transpus indiciile in predicate. Am utilizat doua forme de predicate. % Primul tip pentru toate indiciile cu exceptia lui H si I, in care am exprimat valorile valide apoi am utilizat iteratia. % Predicatul este adevarat cand lista contine valoarea buna. % Celalalt predicat (pentru indiciile H si I) consta in specificarea faptului ca al N-lea element contine anumite valori. % a. Englezul traieste n casa rosie. indiciu1([(englez,rosie,_, _, _)|_]). indiciu1([_|T]) :- indiciu1(T). % b. Suedezul detine cini. indiciu2([(suedez,_,_,_,caini)|_]). indiciu2([_|T]) :- indiciu2(T).

% c. Danezul bea ceai. indiciu3([(danez,_,ceai,_,_)|_]). indiciu3([_|T]) :- indiciu3(T). % d. Casa verde este lnga si la stnga casei albe. indiciu4([(_,verde,_,_,_),(_,alba,_,_,_)|_]). indiciu4([_|T]) :- indiciu4(T). % e. Proprietarul casei verzi bea cafea. indiciu5([(_,verde,cafea,_,_)|_]). indiciu5([_|T]) :- indiciu5(T). % f. Persoana ce fumeaza Pall Mall detine pasari. indiciu6([(_,_,_,pallmall,pasari)|_]). indiciu6([_|T]) :- indiciu6(T). % g. Proprietarul casei galbene fumeaza Dunhill. indiciu7([(_,galbena,_,dunhill,_)|_]). indiciu7([_|T]) :- indiciu7(T). % h. Proprietarul casei din centru bea lapte. indiciu8(Persoane) :- persoana(3, Persoane, (_,_,lapte,_,_)). % i. Norvegianul traieste n prima casa. indiciu9(Persoane) :- persoana(1, Persoane, (norvegian,_,_,_,_)). % j. Persoana ce fumeaza Blends traieste lnga cel ce detine pisici. indiciu10([(_,_,_,blends,_),(_,_,_,_,pisici)|_]). indiciu10([(_,_,_,_,pisici),(_,_,_,blends,_)|_]). indiciu10([_|T]) :- indiciu10(T). % k. Persoana ce detine cai traieste lnga cea ce fumeaza Dunhill. indiciu11([(_,_,_,dunhill,_),(_,_,_,_,cai)|_]). indiciu11([(_,_,_,_,cai),(_,_,_,dunhill,_)|_]). indiciu11([_|T]) :- indiciu11(T). % l. Persoana ce fumeaza Blue Master bea bere. indiciu12([(_,_,bere,bluemaster,_)|_]). indiciu12([_|T]) :- indiciu12(T).

% m. Germanul fumeaza Prince. indiciu13([(german,_,_,prince,_)|_]). indiciu13([_|T]) :- indiciu13(T). % n. Norvegianul traieste lnga casa albastra. indiciu14([(norvegian,_,_,_,_),(_,albastra,_,_,_)|_]). indiciu14([(_,albastra,_,_,_),(norvegian,_,_,_,_)|_]). indiciu14([_|T]) :- indiciu14(T). % o. Persoana ce fumeaza Blends are un vecin ce bea apa. indiciu15([(_,_,_,blends,_),(_,_,apa,_,_)|_]). indiciu15([(_,_,apa,_,_),(_,_,_,blends,_)|_]). indiciu15([_|T]) :- indiciu15(T). % Intrebarea: Cine detine acvariul cu pesti ? intrebare([(_,_,_,_,pesti)|_]). intrebare([_|T]) :- intrebare(T). % Dupa toate acestea urmeaza solutionarea problemei % Spunem ca solutia este o combinatie a tuturor indiciilor si a intrebarii, astfel incat solutia sa valideze toate predicatele. solutia(Persoane) :persoane(5, Persoane), indiciu1(Persoane), indiciu2(Persoane), indiciu3(Persoane), indiciu4(Persoane), indiciu5(Persoane), indiciu6(Persoane), indiciu7(Persoane), indiciu8(Persoane), indiciu9(Persoane), indiciu10(Persoane), indiciu11(Persoane), indiciu12(Persoane), indiciu13(Persoane), indiciu14(Persoane), indiciu15(Persoane), intrebare(Persoane).

Interogare:

1.3 Problema celor N-Dame


Problema const n poziionarea a unui numr N de dame pe o tabl de ah de dimensiuni N x N astfel nct nicio dam s se atace. n mod evident, nu putem avea mai mult de o regin pe rnd. Prin urmare putem descrie o poziie pe tabla de ah doar prin listarea poziiilor de pe coloan a damelor corespunztoare. Spre exemplu o list [c1 c2 c3 c4 c5 ... cn] de n numere ne arat c prima regin se afl pe rndul 1 i coloana 1, a doua pe rndul 2 i coloana 2 etc. Dou dame, de asemenea, nu pot sta n siguran pe aceeai coloan, prin urmare toate numerele listei [c1 ... cn] sunt diferite. Astfel, putem reformula problema prin cutarea permutrii unei liste [1 2 3 ... n] ce poate descrie o poziie n siguran a N regine.

Enun:
S se proiecteze un cod surs n SWI-Prolog care s indice poziiile pe care trebuie s se aeze N dame pe o tabl de ah de dimensiune N x N astfel nct nicio dam s nu se atace.

10

Codul surs:
% Urmatorul predicat verifica daca o pozitie este sigura. % Pozitia este sigura daca prima dama nu le ataca pe celelalte si pozitiile celorlalte dame sunt sigure. % Dupa cum reprezentarea pozitiilor de pe tabla garanteaza ca nicio dama nu se afla pe acelasi rand sau coloana, trebuie verificate doar diagonala. % Dama (i,ci) poata ataca dama (j,cj) numai daca i-j = ci-cj, sau i-j = cj-ci. % Cu alte cuvinte, daca distanta intre randurile a doua dame este d, ele nu se ataca doar daca niciuna din relatiile % cj-ci = d si ci-cj = d nu este valabila. % Verificam sa vedem daca o dama pozitionata pe o coloana col si pe randurile 'dist_rand' % deasupra primei dame din lista L ataca pe cineva din lista regina_nu_ataca(_,_,[]) :- !. regina_nu_ataca(Col,Dist_rand,[O_regina_col|Alte_regine]) :- !, Diag_hit_col1 is Col + Dist_rand, O_regina_col =\= Diag_hit_col1, Diag_hit_col2 is Col - Dist_rand, O_regina_col =\= Diag_hit_col2, Dist_rand1 is Dist_rand + 1, regina_nu_ataca(Col,Dist_rand1,Alte_regine).

pozitie_sigura([_]) :- !. pozitie_sigura([O_regina|Alte_regine]) :- !, regina_nu_ataca(O_regina,1,Alte_regine), pozitie_sigura(Alte_regine). % Urmatoarea functie verifica o distributie sigura completa. % Produce permutari a unei liste date si verifica sa vada daca corespunde unei pozitii sigure. insereaza(X,Y,[X|Y]). insereaza(X,[Y1|Y2],[Y1|Z]) :- insereaza(X,Y2,Z). permuta([X],[X]). permuta([X|Y],Z) :- permuta(Y,Z1), insereaza(X,Z1,Z). distributie_sigura(Distributie,Distributie1) :permuta(Distributie,Distributie1), pozitie_sigura(Distributie1). distributie_sigura_tot(Distributie) :nl,nl,print('Rezolvarea unei probleme de n-dame unde n='), length(Distributie,N), print(N), nl,distributie_sigura(Distributie,Distributie1), print(Distributie1),nl,fail. distributie_sigura_tot(_).

11

Interogare:

1.4 Misionari si canibali


Pe malul unui ru se afl 3 misionari i 3 canibali ce doresc traversarea pe malul opus, avnd la dispoziie o singur barc ce poate cra maxim dou persoane pe deplasare. a. Obiectivul: Deplasarea tuturor misionarilor i canibalilor pe cellalt mal. b. Constrngere: Misionarii nu trebuie niciodat s fie numeric mai puini dect canibalii, pe orice parte a rului, altfel fiind ucii. c. Operatori: Deplasai barca cu ocupani de-a lungul rului (n orice direcie) ctre cellalt mal.

Enun:
S se proiecteze un cod surs n SWI-Prolog care s indentifice i s afieze numrul minim de deplasri legale prin care toi misionarii i canibalii s fie deplasai pe malul opus. (cel mai mic numr de deplasri: 11)

12

Codul surs:
start(stare(mal(l,3,3),mal(r,0,0),barca_stanga)). obiectiv(stare(mal(l,0,0),mal(r,3,3),barca_dreapta)). sigur_mal(mal(_,M,C)):M=0,!; C=0,!; M>=C. % sigur_stare(stare(L,R,_B)):-sigur_mal(L),sigur_mal(R). urm_stare(stare(Dela1,La1,barca_stanga),stare(Dela2,La2,barca_dreapta)):muta(Dela1,La1,Dela2,La2). urm_stare(stare(La1,Dela1,barca_dreapta),stare(La2,Dela2,barca_stanga)):muta(Dela1,La1,Dela2,La2). muta(BDela1,BLa1,BDela2,BLa2):BDela1=mal(BF,Mf1,Cf1), BLa1=mal(BT,Mt1,Ct1), BDela2=mal(BF,Mf2,Cf2), BLa2=mal(BT,Mt2,Ct2), member(DM/DC,[0/1,0/2,1/0,1/1,2/0]), Mf1>=DM, Cf1>=DC, Mf2 is Mf1-DM, Cf2 is Cf1-DC, sigur_mal(BDela2), Mt2 is Mt1+DM, Ct2 is Ct1+DC, sigur_mal(BLa2). solutie(Obiectiv,Obiectiv,CaleGasita,CaleGasita):-!. solutie(Stare,_Obiectiv,[_Current|Cale],_CaleGasita):-member(Stare,Cale),!,fail. solutie(Stare1,Obiectiv,Cale,CaleGasita):urm_stare(Stare1,Stare2), solutie(Stare2,Obiectiv,[Stare2|Cale],CaleGasita). print_cale([]):-!,nl. print_cale([Current|Cale]):-print_cale(Cale),print_stare(Current). print_stare(stare(BL,BR,BT)):-print_mal(BL),print_boat(BT),print_mal(BR),nl. print_mal(mal(_,M,C)):-print_persoane(m,M,3),write(' '),print_persoane(c,C,3). print_persoane(Chr,N,Lat):-print_chars(Chr,N),Empty is 13

Lat-N,print_chars('-',Empty). print_chars(_Chr,0):-!. print_chars(Chr,N):-write(Chr),N1 is N-1,print_chars(Chr,N1). print_boat(boat_left):-write('\\__/'). print_boat(boat_right):-write(' \\__/ '). solutie:start(Start),obiectiv(Obiectiv),solutie(Start,Obiectiv,[Start],CaleGasita),print_cale(CaleG asita),fail;true.

Interogare:

14

2. Probleme de dificultate medie

2.1 Relatii de familie


Enun:
Fiind dat urmtorul arbore genealogic, s se proiecteze un cod surs n SWI-Prolog care s determine gradul de rudenie ntre dou persoane.

Codul surs:
parinte(ana,alex). parinte(george,alex). parinte(george,aurelia). parinte(alex,adriana). parinte(alex,elena). parinte(elena,vasile). feminin(ana). feminin(aurelia). feminin(adriana). feminin(elena).

15

masculin(george). masculin(alex). masculin(vasile). sex(ana,feminin). sex(aurelia,feminin). sex(adriana,feminin). sex(elena,feminin). sex(george,masculin). sex(alex,masculin). sex(vasile,masculin). diferit(X,Y) :- X\==Y. bunic(X) :- parinte(X,Z), parinte(Z,_), masculin(X). bunic(X,Y) :- parinte(X,Z), parinte(Z,Y), masculin(X). bunica(X) :- parinte(X,Z), parinte(Z,_), feminin(X). bunica(X,Y) :- parinte(X,Z), parinte(Z,Y), feminin(X). mama(X,Y) :- parinte(X,Y), feminin(X). tata(X,Y) :- parinte(X,Y), masculin(X). frate(X,Y) :- parinte(Z,X), parinte(Z,Y), masculin(X), diferit(X,Y). sora(X,Y) :- parinte(Z,X), parinte(Z,Y), feminin(X), diferit(X,Y). unchi(X,Y) :- parinte(Z,Y), (frate(Z,X); sora(Z,X)), masculin(X). matusa(X,Y) :- parinte(Z,Y), (frate(Z,X); sora(Z,X)), feminin(X). predecesor(X,Y) :- parinte(X,Y). predecesor(X,Y) :- parinte(X,Z), predecesor(Z,Y). rude(X,Y) :- predecesor(X,Y); predecesor(Y,X). rude(X,Y) :- predecesor(Z,X), predecesor(Z,Y). rude(X,Y) :- predecesor(X,Z), predecesor(Y,Z).

Interogri:
16

17

2.2 Operaii cu liste


Enun:
S se proiecteze un cod surs n SWI-Prolog care s efectueze urmtoarele operaii cu liste: - cte elemente sunt n list; - dac X este element al listei; - stergerea unui element din list; - inserarea unui element n list; - concatenarea a 2 liste; - lipirea inversului unei liste la o alt list; - permutarea elementelor dintr-o list; - sublista unei liste; - ultimul element din list; - primul element din list.

Codul surs:
l([],0). % lista vida l([_|T],N) :- l(T,N1), N is 1+N1. % N=numarul de elemente ale listei member(X,[Y|T]) :- X==Y ; member(X,T). %X membru al listei care incepe cu Y daca Y=X sau % X este membru al listei T delete(X,[X|T],T). % sterge elementul X din capul listei delete(X,[Y|T],[Y|T1]) :- delete(X,T,T1). % sterge elementul X din list insert(X,L,L1) :- delete(X,L1,L). % insereaz elementul X n lista L concat([],L,L). concat([X|L1],L2,[X|L3]) :- concat(L1,L2,L3). % concateneaz lista [X|L1] la lista L2 reverse([],L,L). reverse([X|L1],L2,L3) :- reverse(L1,[X|L2],L3). % concateneaz lista [X|L1], inversat, la lista % L2 reverse(A,R) :- reverse(A,[],R). % spune dac lista A este inversul listei R perm([],[]). perm([X|L],P) :- perm(L,L1),insert(X,L1,P). % afiseaz toate permutrile elementelor din lista % [X|L] subset([],_). subset([X|R],S) :- member(X,S), subset(R,S). % spune dac lista [X|R] este sublist a listei S ultim(X,[H]) :- X=H. ultim(X,[_|T]) :- ultim(X,T). % spune dac X este ultimul element din lista [H] sau care e ultimul element din list prim(X,[H|T]) :- X=H. % spune dac X este primul element din lista [H|T] sau care e primul element din list 18

Interogri:

19

2.3 Problema celor 4 specialiti


James, Tom, Bob si Jim tiu fiecare cte un singur i diferit limbaj de programare (HTML, C++, Java, respectiv Prolog) i sunt specializai n cte un domeniu diferit (matematic, fizic, chimie, biologie). Se tiu urmtoarele: a) cel care programeaz n Java e specializat n biologie; b) Tom nu stie nici Prolog, nici HTML i nu e specializat pe matematic; c) James nu stie nici Prolog, nici HTML i nu e specializat pe matematic; d) cel care e specializat n chimie nu programeaz n HTML; e) Bob e specialzat n fizic i nu programeaz n Prolog

Enun:
S se proiecteze un cod surs n SWI-Prolog n care s se afieze ce limbaj de programare tie fiecare i n ce domeniu e specializat.

Cod surs:
nume(james). nume(tom). nume(bob). nume(jim). limbaj(html). limbaj(cpp). limbaj(java). limbaj(prolog). domeniu(matematica). domeniu(fizica). domeniu(chimie). domeniu(biologie). regula1(Y,Z):- Y=biologie, !, Z=java. regula1(_,_). regula2(X,Y,Z):- X=tom, !, Y\==matematica, Z\==prolog, Z\==html. regula2(_,_,_). regula3(X,Y,Z):- X=james, !, Y\==matematica, Z\==prolog, Z\==html. regula3(_,_,_). regula4(Y,Z):- Y=chimie, !, Z\==html. regula4(_,_).

20

regula5(X,Y,Z):- X=bob, !, Y=fizica, Z\==prolog. regula5(_,_,_). rezolva(X,Y,Z):- nume(X), domeniu(Y), limbaj(Z), regula1(Y,Z), regula2(X,Y,Z), regula3(X,Y,Z), regula4(Y,Z), regula5(X,Y,Z). diferit(X1,X2,X3,X4):- X1\==X2, X1\==X3, X1\==X4, X2\==X3, X2\==X4, X3\==X4. solutie(Y1,Z1,Y2,Z2,Y3,Z3,Y4,Z4):- rezolva(james,Y1,Z1), rezolva(tom,Y2,Z2), rezolva(bob,Y3,Z3), rezolva(jim,Y4,Z4), diferit(Y1,Y2,Y3,Y4), diferit(Z1,Z2,Z3,Z4).

Interogare:

21

2.4 Maimua i banana


Avem o maimu ntr-o ncpere. n mijlocul camerei se afl o banan atrnat de tavan. Maimua vrea s ia banana dar nu poate ajunge pn la ea. n camer se mai afl o cutie, poziionat n dreptul ferestrei, pe care maimua o poate folosi. Maimua poate realiza urmtoarele aciuni : - s mearg pe podea - s se urce pe cutie - s mping cutia - s ia banana dac st pe cutie chiar sub banan Poate lua maimua banana ?

Enun:
S se proiecteze un cod surs n SWI-Prolog care s rspund dac maimua dintr-o stare poate lua banana.

Cod surs:
% starile stare(la_usa, pe_podea , la_fereastra , nu_are). stare(la_mijloc, pe_podea, la_fereastra, nu_are). stare(la_fereastra, pe_podea, la_fereastra , nu_are). stare(la_fereastra, pe_cutie, la_fereastra, nu_are). stare(mijloc, pe_podea, mijloc, nu_are). stare(mijloc, pe_cutie, mijloc, nu_are). stare(mijloc, pe_cutie, mijloc, are). % miscarile miscare(stare(mijloc, pe_cutie, mijloc, nu_are), ia, stare(mijloc, pe_cutie, mijloc , are)). miscare(stare(P, pe_podea, P, H), urca, stare(P, pe_cutie, P, H)). miscare(stare(P1, pe_podea, P1, H), impinge, stare(P2, pe_podea, P2,H)). miscare(stare(P1,pe_podea,B,H), 22

merge(P1,P2), stare(P2,pe_podea,B,H)). % poate lua poate_lua(stare(_,_,_,are)). poate_lua(Stare1):miscare(Stare1,M,Stare2), poate_lua(Stare2).

Interogri:

23

3. Probleme de dificultate redus


3.1 irul lui Fibonacci
Formula de recuren a irului lui Fibonacci este: Xn = Xn-1 + Xn-2 , unde n>2, iar X1=1 si X2=1. Mulimea termenilor irului este {1, 1, 2, 3, 5, 8, 13, 21, ...}.

Enun:
S se proiecteze un cod surs n SWI-Prolog care sa afiseze al n-lea numr din sirul Fibonacci.

Cod surs:
fib(1,1). % X1=1 fib(2,1). % X2=1 fib(N,F) :N>2, N1 is N-1, fib(N1,F1), N2 is N-2, fib(N2,F2), F is F1 + F2.

Interogri:

24

3.2 Problema turnurilor din Hanoi


Obiectivul acestei probleme faimoase este s mutm n-discuri de pe un turn din stnga pe un turn din dreapta folosind un turn intermediar central ca auxiliar. Niciun moment nu trebuie s fie pus un disc de dimensiune mai mare peste unul de dimensiune mai mica.

Enun:
S se proiecteze un cod surs n SWI-Prolog care s determine i s afieze mutrile necesare pentru a deplasa toate discurile pe al treilea turn.

Cod surs:
mutare(0,_,_,_) :- ! . % cnd avem 0 discuri nu se face nimic % (oprirea procesului de cautare) mutare(N,A,B,C) :- N1 is N-1, mutare(N1,A,C,B), scrie(A,B), mutare(N1,C,B,A). scrie(X,Y) :- write([mutare,X,Y]), nl.

Interogri:

25

3.3 Minimul, maximul, c.m.m.d.c. a 2 numere i maximul i minimul elementelor unei liste
Enun:
S se proiecteze un cod surs n SWI-Prolog care s determine minimul, maximul, c.m.m.d.c. a 2 numere i maximul i minimul elementelor unei liste.

Cod surs:
min(A,B,A) :- A<B, !. min(A,B,B). max(A,B,A) :- A>B,!. max(A,B,B). min([X],X). min([X|L],Z) :- min(L,Y), min(X,Y,Z). max([X],X). max([X|L],Z) :- max(L,Y), max(X,Y,Z). cmmdc(A,A,A). cmmdc(A,1,1). cmmdc(1,B,1). cmmdc(A,B,D) :- A>B, Y is A-B, cmmdc(Y,B,D). cmmdc(A,B,D) :- A<B, Y is B-A, cmmdc(A,Y,D).

Interogri:

26

3.4 Derivare simbolic


Enun:
S se proiecteze un cod surs n SWI-Prolog care sa deriveze diferite expresii aritmetice. (David H. D. Warren)

Cod surs:
% prioritatea operatorului de putere :- op(300,xfy,**). % reguli de derivare d(X,X,D) :- atomic(X), !, D=1. d(C,X,D) :- atomic(C), !, D=0. d(U+V,X,DU+DV) :- d(U,X,DU), d(V,X,DV). d(U-V,X,DU-DV) :- d(U,X,DU), d(V,X,DV). d(U*V,X,DU*V+U*DV) :- d(U,X,DU), d(V,X,DV). d(U**N,X,N*U**N1*DU) :- integer(N), N1 is N-1, d(U,X,DU). d(-U,X,-DU) :- d(U,X,DU).

Interogri:

27

28

29

30