Sisteme Expert

Nu esti logat.

Munca individuala laborator 2 - Operatorul de unificare, optimizari

Punctaj: 80p

Nr. 1

  1. Optimizati predicatul propoz(-P). In rezolvare, fiecare test din predicat ar trebui pus pe o linie noua (pentru o citire mai usoara), fiind precedat mereu de apelul predicatului numara_teste (care contorizeaza de cate ori a trecut programul pe acolo). Testarea rezolvarii se va face prin apelul predicatului afiseaza_propoz.

    Atentie, desi poate nu veti intelege inca ce face codul din interiorul predicatelor folosite pentru numararea testelor, pe voi va intereseaza acum doar cum sa le utilizati in rezolvare:

    • init_teste - initializeaza contorul pentru teste. Se apeleaza obligatoriu la inceputul predicatului propoz
    • numara_teste - numara testele. Se apeleaza inaintea fiecarui test din cadrul lui propoz (asa cum se vede in codul dat ca exemplu).
    • afiseaza_teste - afiseaza contorul (numarul de teste efectuate). Se apeleaza obligatoriu la finalul predicatului propoz.
    /*predicate pentru numararea testelor */
    init_teste:- retractall(nr_teste(_)).
    numara_teste:- retract(nr_teste(NV)) -> NN is NV+1, assert(nr_teste(NN)); assert(nr_teste(1)).
    afiseaza_teste:- nr_teste(N), format('Numar total teste ~d \n',[N]).


    sintagma('Ion',subiect).
    sintagma(pisica,subiect).
    sintagma(prinde,predicat).
    sintagma('o casa',subiect).
    sintagma(soareci,complement).
    sintagma(tractorul,subiect).
    sintagma(viseaza,predicat).
    sintagma(prajituri,complement).
    sintagma('o casa',complement).

    propoz(Prop):-
        init_teste,
        numara_teste, sintagma(Subiect, TipS),
        numara_teste, sintagma(Predicat, TipP),
        numara_teste, sintagma(Complement, TipC),
        numara_teste, TipS==subiect,
        numara_teste, TipP==predicat,
        numara_teste, TipC==complement,
        numara_teste, Subiect \== Complement,
        numara_teste, Prop= propoz(Subiect,Predicat, Complement),
        afiseaza_teste.

    afiseaza_propoz:- propoz(Prop),write(Prop),nl,nl,fail;true.
    Predicatul afiseaza_propoz initial va avea ca output: | ?- afiseaza_propoz.
    Numar total teste 58
    propoz(Ion,prinde,soareci)

    Numar total teste 69
    propoz(Ion,prinde,prajituri)

    Numar total teste 74
    propoz(Ion,prinde,o casa)

    Numar total teste 149
    propoz(Ion,viseaza,soareci)

    Numar total teste 160
    propoz(Ion,viseaza,prajituri)

    Numar total teste 165
    propoz(Ion,viseaza,o casa)

    Numar total teste 260
    propoz(pisica,prinde,soareci)

    Numar total teste 271
    propoz(pisica,prinde,prajituri)

    Numar total teste 276
    propoz(pisica,prinde,o casa)

    Numar total teste 351
    propoz(pisica,viseaza,soareci)

    Numar total teste 362
    propoz(pisica,viseaza,prajituri)

    Numar total teste 367
    propoz(pisica,viseaza,o casa)

    Numar total teste 553
    propoz(o casa,prinde,soareci)

    Numar total teste 564
    propoz(o casa,prinde,prajituri)

    Numar total teste 643
    propoz(o casa,viseaza,soareci)

    Numar total teste 654
    propoz(o casa,viseaza,prajituri)

    Numar total teste 844
    propoz(tractorul,prinde,soareci)

    Numar total teste 855
    propoz(tractorul,prinde,prajituri)

    Numar total teste 860
    propoz(tractorul,prinde,o casa)

    Numar total teste 935
    propoz(tractorul,viseaza,soareci)

    Numar total teste 946
    propoz(tractorul,viseaza,prajituri)

    Numar total teste 951
    propoz(tractorul,viseaza,o casa)

    yes
    | ?-

    Practic inaintea fiecarei solutii este afisat numarul de teste efectuat pentru a obtine acea solutie. Ce aveti de facut este sa reordonti sau sa comprimati testele din propoz astfel incat sa obtineti un numar cat mai mic de teste.

  2. In acest exercitiu va trebui sa corectati predicatul stiva(-Cub1, -Cub2, -Cub3). Acesta doreste sa creeze stive de cate exact 3 cuburi cu urmaoarele proprietati:
    • masa cuburilor (suma kilogramelor) de deasupra unui cub nu are voie sa depaseasca masa cubului respectiv. De exemplu pe un cub de masa 10 nu pot sta asezate un cub de masa 7 si unul de masa 4, deoarece 10 < 7+4. Dar pe cubul de masa 10 ar putea sta un cub de masa 7 si unul de masa 3.
    • nu putem pune un cub de latura mai mare peste unul de latura mai mica.
    • cuburile in stiva trebuie sa fie in ordine alfabetica (pornind din varful stivei spre baza)
    • inaltimea totala a stivei trebuie sa se regaseasca in lista de inaltimi admise ( care se gaseste in predicatul inaltimi)
    inaltimi_admise([5, 10, 15, 20, 64, 70]).
    %cub(nume,latura, greutate)
    cub(a,10,3).
    cub(b,30,20).
    cub(c,5,5).
    cub(d,8,10).
    cub(e,4,1).
    cub(f,10,3).
    cub(g,50,5).
    cub(h,20,11).
    cub(i,40,18).

    stiva(Cub1, Cub2, Cub3):- Cub1 <Cub2 <Cub3, cub(Cub1, D1, G1), cub(Cub2, D2, G2), cub(Cub3, D3, G3), inalt is D1+D2+D3, member(Inalt,inaltimi_admise(LI)),G3>G2+G1, G2>G1, D3>D2, D2>D1.

    Predicatul stiva ar trebui sa aiba outputul:

    | ?- stiva(A,B,C).
    A = a,
    B = h,
    C = i ? ;
    A = e,
    B = f,
    C = g ? ;
    A = e,
    B = h,
    C = i ? ;
    A = f,
    B = h,
    C = i ? ;
    no
    | ?-
  3. Se considera faptele: soarece('Chit').
    soarece('Rontz').
    soarece('Cascaval-Finder').
    pisica('Miau').
    pisica('Madeleine Gherutzescu').
    pisica('Motanovski').
    Sa se scrie un predicat afisSoarecPisic(+Litera) care afiseaza toti soarecii si toate pisicile din baza de cunostinte cu proprietatea ca au acea litera in nume. Exemplu: | ?- afisSoarecPisic(a).
    Cascaval-Finder
    Miau
    Madeleine Gherutzescu
    Motanovski
    yes
    | ?-
  4. Se da urmatoarea baza de cunostinte: grup(g1, exp(e1,2+3-7), exp(e2,3+5+1), exp(e3,1-1-1)).
    grup(g2, exp(e4,5-2-2), exp(e5,1+1-1), exp(e6,2+2-3)).
    grup(g3, exp(e7,7-2), exp(e8,5-2-1), exp(e9,3+2-14)).
    grup(g4, exp(e10,3+4-0), exp(e11,7), exp(e12,7+7-7)).
    grup(g5, exp(e13,3-11+1), exp(e14,2+3+3), exp(e15,11-1-2)).
    grup(g6, exp(e16,2+3), exp(e17,1+1+1), exp(e18,3+5)).
    Sa se rezolve subpunctele:
    1. un predicat care da ca solutii, pe rand, grupurile cu toate expresiile egale: egal_exp(-G) | ?- egal_exp(G).
      G = g2 ? ;
      G = g4 ? ;
      no
    2. un predicat care da ca solutii grupurile care au cel putin o expresie cu un numar de operanzi diferit de 3 (operatiile posibile sunt doar adunare si scadere): gr_exp_not3(-G). | ?- gr_exp_not3(G).
      G = g3 ? ;
      G = g4 ? ;
      G = g6 ? ;
      no
      | ?-
    3. un predicat care da ca solutii toate perechiile de grupuri G1, G2, cu proprietatea ca suma expresiilor lui G1 este mai mica decat suma expresiilor lui G2. Rezultatele se vor da sub forma pereche(sum(G1,S1),sum(G2,S2)). | ?- per(P).
      P = pereche(sum(g1,6),sum(g4,21)) ? ;
      P = pereche(sum(g1,6),sum(g5,9)) ? ;
      P = pereche(sum(g1,6),sum(g6,16)) ? ;
      P = pereche(sum(g2,3),sum(g1,6)) ? ;
      P = pereche(sum(g2,3),sum(g4,21)) ? ;
      P = pereche(sum(g2,3),sum(g5,9)) ? ;
      P = pereche(sum(g2,3),sum(g6,16)) ? ;
      P = pereche(sum(g3,-2),sum(g1,6)) ? ;
      P = pereche(sum(g3,-2),sum(g2,3)) ? ;
      P = pereche(sum(g3,-2),sum(g4,21)) ? ;
      P = pereche(sum(g3,-2),sum(g5,9)) ? ;
      P = pereche(sum(g3,-2),sum(g6,16)) ? ;
      P = pereche(sum(g5,9),sum(g4,21)) ? ;
      P = pereche(sum(g5,9),sum(g6,16)) ? ;
      P = pereche(sum(g6,16),sum(g4,21)) ? ;
      no
      | ?-
    4. un predicat care da ca solutii toate perechiile de expresii din grupuri diferite, a caror suma este nula. Rezultatul se va da sub forma rez(NumeExp1/Grup1+NumeExp2/Grup2=(Exp1)+(Exp2), nul). | ?- per_expresii(Rez).
      Rez = rez(e3/g1+e4/g2=1-1-1+(5-2-2),nul) ? ;
      Rez = rez(e3/g1+e5/g2=1-1-1+(1+1-1),nul) ? ;
      Rez = rez(e3/g1+e6/g2=1-1-1+(2+2-3),nul) ? ;
      Rez = rez(e1/g1+e8/g3=2+3-7+(5-2-1),nul) ? ;
      Rez = rez(e2/g1+e9/g3=3+5+1+(3+2-14),nul) ? ;
      Rez = rez(e4/g2+e3/g1=5-2-2+(1-1-1),nul) ? ;
      Rez = rez(e5/g2+e3/g1=1+1-1+(1-1-1),nul) ? ;
      Rez = rez(e6/g2+e3/g1=2+2-3+(1-1-1),nul) ? ;
      Rez = rez(e8/g3+e1/g1=5-2-1+(2+3-7),nul) ? ;
      Rez = rez(e9/g3+e2/g1=3+2-14+(3+5+1),nul) ? ;
      Rez = rez(e10/g4+e13/g5=3+4-0+(3-11+1),nul) ? ;
      Rez = rez(e11/g4+e13/g5=7+(3-11+1),nul) ? ;
      Rez = rez(e12/g4+e13/g5=7+7-7+(3-11+1),nul) ? ;
      Rez = rez(e13/g5+e10/g4=3-11+1+(3+4-0),nul) ? ;
      Rez = rez(e13/g5+e11/g4=3-11+1+7,nul) ? ;
      Rez = rez(e13/g5+e12/g4=3-11+1+(7+7-7),nul) ? ;
      no
      | ?-

Nr. 2

  1. Optimizati predicatul echipa(-P). Predicatul echipa(-P) construieste echipele de cate 2 elevi (evident diferiti), care au notele mai mari ca 5 si media notelor lor mai mare ca 7. Echipele sunt de forma echipa(e1(Nume1,Prenume1),e2(Nume2, Prenume2), Medie). In rezolvare, fiecare test din predicat ar trebui pus pe o linie noua (pentru o citire mai usoara), fiind precedat mereu de apelul predicatului numara_teste (care contorizeaza de cate ori a trecut programul pe acolo). Testarea rezolvarii se va face prin apelul predicatului afiseaza_echipe.

    Atentie, desi poate nu veti intelege inca ce face codul din interiorul predicatelor folosite pentru numararea testelor, pe voi va intereseaza acum doar cum sa le utilizati in rezolvare:

    • init_teste - initializeaza contorul pentru teste. Se apeleaza obligatoriu la inceputul predicatului echipa
    • numara_teste - numara testele. Se apeleaza inaintea fiecarui test din cadrul lui echipa (asa cum se vede in codul dat ca exemplu).
    • afiseaza_teste - afiseaza contorul (numarul de teste efectuate). Se apeleaza obligatoriu la finalul predicatului echipa.
    /*predicate pentru numararea testelor */
    init_teste:- retractall(nr_teste(_)).
    numara_teste:- retract(nr_teste(NV)) -> NN is NV+1, assert(nr_teste(NN)); assert(nr_teste(1)).
    afiseaza_teste:- nr_teste(N), format('Numar total teste ~d \n',[N]).


    %elev(nume, prenume, nota)
    elev('Popescu','Ion',7).
    elev('Dorel','Doru', absent).
    elev('Georgescu','Gigel',10).
    elev('Danescu','Ion',4).
    elev('Tache','Lulu',4).
    elev('Costache','Costin',8).
    elev('Marinescu','Maria',5).
    elev('Petrescu','Petre', absent).
    elev('Gogulescu','Gogu',3).


    echipa(Ech):-
        init_teste,
        numara_teste, elev(Nume1, Prenume1, Nota1),
        numara_teste, elev(Nume2, Prenume2, Nota2),
        numara_teste, Nume1 \== Nume2,
        numara_teste, Prenume1 \== Prenume2,
        numara_teste, number(Nota1),
        numara_teste, number(Nota2),
        numara_teste, Medie is (Nota1+Nota2)/2,
        numara_teste, Nota1>=5,
        numara_teste, Nota2>=5,
        numara_teste, Ech = echipa(e1(Nume1,Prenume1),e2(Nume2, Prenume2), Medie),
        numara_teste, Medie>=7,
        afiseaza_teste.
        


    afiseaza_echipe:- echipa(Ech),write(Ech),nl,nl,fail;true.

    Predicatul afiseaza_echipe initial va avea ca output: | ?- afiseaza_echipe.
    Numar total teste 16
    echipa(e1(Popescu,Ion),e2(Georgescu,Gigel),8.5)

    Numar total teste 34
    echipa(e1(Popescu,Ion),e2(Costache,Costin),7.5)

    Numar total teste 90
    echipa(e1(Georgescu,Gigel),e2(Popescu,Ion),8.5)

    Numar total teste 118
    echipa(e1(Georgescu,Gigel),e2(Costache,Costin),9.0)

    Numar total teste 127
    echipa(e1(Georgescu,Gigel),e2(Marinescu,Maria),7.5)

    Numar total teste 236
    echipa(e1(Costache,Costin),e2(Popescu,Ion),7.5)

    Numar total teste 249
    echipa(e1(Costache,Costin),e2(Georgescu,Gigel),9.0)

    Numar total teste 307
    echipa(e1(Marinescu,Maria),e2(Georgescu,Gigel),7.5)

    yes
    | ?-

    Practic inaintea fiecarei solutii este afisat numarul de teste efectuat pentru a obtine acea solutie. Ce aveti de facut este sa reordonati sau sa comprimati testele din echipa astfel incat sa obtineti un numar cat mai mic de teste.

  2. In acest exercitiu va trebui sa corectati predicatul asezare(-Cub1, -Cub2, -Cub3) si, eventual, alte predicate auxiliare. Acesta doreste sa creeze asezari orizontale de cate exact 3 cuburi cu urmaoarele proprietati:
    • masa totala a cuburilor (suma kilogramelor) sa nu depaseasca valoarea din greutate_max.
    • diferenta de inaltime dintre doua cuburi consecutive trebuie sa se regaseasca in lista de inaltimi admise.
    • cuburile in asezare trebuie sa fie diferite intre ele
    diferente_admise([10, 40]).
    %cub(nume, latura, greutate).
    cub(a,10,3).
    cub(b,30,20).
    cub(c,5,5).
    cub(d,8,10).
    cub(e,4,1).
    cub(f,10,3).
    cub(g,50,5).
    cub(h,20,11).
    cub(i,40,18).
    greutate_max(20).

    diferenta_inalt(x,y,abs(x-y)).

    asezare(Cub1, Cub2, Cub3):- Cub1 =\= Cub2,Cub2 =\= Cub3,   cub(Cub1, D1, G1), cub(Cub2, D2, G2), cub(Cub3, D3, G3), diferente_admise(Ld),diferenta_inalt(D1,D2,Dif),member( Dif, Ld),diferenta_inalt(D2,D3,Dif),member(Dif, Ld), G1+G2+G3 < greutate_max(g).

    Predicatul asezare ar trebui sa aiba outputul:

    | ?- asezare_corectat(Cub1, Cub2, Cub3).
    Cub1 = a,
    Cub2 = g,
    Cub3 = f ? ;
    Cub1 = a,
    Cub2 = h,
    Cub3 = f ? ;
    Cub1 = f,
    Cub2 = g,
    Cub3 = a ? ;
    Cub1 = f,
    Cub2 = h,
    Cub3 = a ? ;
    Cub1 = g,
    Cub2 = a,
    Cub3 = h ? ;
    Cub1 = g,
    Cub2 = f,
    Cub3 = h ? ;
    Cub1 = h,
    Cub2 = a,
    Cub3 = g ? ;
    Cub1 = h,
    Cub2 = f,
    Cub3 = g ? ;
    no
  3. Se considera faptele: cuvant(abc).
    cuvant(abfgh).
    cuvant(dududu).
    cuvant(lala).
    cuvant(lalila).
    cuvant(abab).
    Sa se scrie un predicat fara parametri, afis_per_cuv, care afiseaza toate perechiile de cuvinte care incep cu aceleasi doua litere fie in ordinea in care apar in primul cuvant, fie inversate (de exemplu, daca un cuvant incepe cu ab, celalalt poate incepe cu ab sau cu ba). Perechiile se vor afisa cate una pe un rand, cuvintele fiind separate prin - (minus). Perechiile se pot repeta, in sensul ca daca a fost afisata o pereche de forma cuv1-cuv2, e ok sa se afiseze si cuv2-cuv1. Exemplu: | ?- afis_per_cuv.
    abc-abfgh
    abc-abab
    abfgh-abc
    abfgh-abab
    lala-lalila
    lalila-lala
    abab-abc
    abab-abfgh
    yes
    | ?-
  4. Se da urmatoarea baza de cunostinte: grup(g1, exp(e1,2+3-7), exp(e2,3+5+1)).
    grup(g2, exp(e3,5-2-2), exp(e4,1+1-1)).
    grup(g3, exp(e5,7-2), exp(e6,5-2-1)).
    grup(g4, exp(e7,3+4-0), exp(e8,7)).
    grup(g5, exp(e11,3-11+1), exp(e10,2+3+3)).
    grup(g6, exp(e12,2+3), exp(e13,1+1+1)).
    grup(g7, exp(e13,1-1-1), exp(e14,1+1+1)).
    Sa se rezolve subpunctele:
    1. un predicat care da ca solutii, pe rand, grupurile cu prima expresie mai mica decat N si a doua mai mare: compar_N(+N,-G) | ?- compar_N(0, G).
      G = g1 ? ;
      G = g5 ? ;
      G = g7 ? ;
      no
    2. un predicat care da ca solutii, pe rand, grupurile care au minim o expresie (cu 3 operanzi) cu toti operanzii egali : egal_op(-G). | ?- egal_op(G).
      G = g2 ? ;
      G = g6 ? ;
      G = g7 ? ;
      no
      | ?-
    3. un predicat care da ca solutii toate perechiile de grupuri G1, G2, diferite, cu proprietatea ca mediile expresiilor lor sunt egale. Rezultatele se vor da sub forma pereche(med(G1,S1),med(G2,S2)). | ?- per(G).
      G = pereche(med(g1,3.5),med(g3,3.5)) ? ;
      G = pereche(med(g2,1.0),med(g7,1.0)) ? ;
      G = pereche(med(g3,3.5),med(g1,3.5)) ? ;
      G = pereche(med(g7,1.0),med(g2,1.0)) ? ;
      no
      | ?-
    4. un predicat care da ca solutii toate perechiile de expresii din grupuri diferite, cu proprietatea ca prima expresie are rezultatul mai mic decat rezultatul celei de-a doua si rezultatele au aceeasi paritate. Rezultatul se va da sub forma rez(NumeExp1/Grup1+NumeExp2/Grup2=(Exp1)+(Exp2), nul) rez(NumeExp1-Grup1<NumeExp1-Grup1,adica(Rez1<Rez2)). Iata primele solutii (sunt foarte multe asa ca nu le-am pus pe toate): | ?- per_expresii(P).
      P = rez(e3-g1<e4-g2,adica(-1<1)) ? ;
      P = rez(e3-g1<e5-g2,adica(-1<1)) ? ;
      P = rez(e3-g1<e6-g2,adica(-1<1)) ? ;
      P = rez(e1-g1<e8-g3,adica(-2<2)) ? ;
      P = rez(e3-g1<e7-g3,adica(-1<5)) ? ;
      P = rez(e3-g1<e10-g4,adica(-1<7)) ? ;
      P = rez(e3-g1<e11-g4,adica(-1<7)) ? ;
      P = rez(e3-g1<e12-g4,adica(-1<7)) ? ;
      P = rez(e1-g1<e14-g5,adica(-2<8)) ? ;
      P = rez(e1-g1<e15-g5,adica(-2<8)) ? ;
      P = rez(e1-g1<e18-g6,adica(-2<8)) ?
      yes
      | ?-

Nr. 3

  1. Optimizati predicatul cifre_cons(-P). Predicatul cifre_cons(-P) gaseste grupurile de catre 3 cifre consecutive, care au suma para. Rezultatele sunt de forma cifre(C1, C2, C3). In rezolvare, fiecare test din predicat ar trebui pus pe o linie noua (pentru o citire mai usoara), fiind precedat mereu de apelul predicatului numara_teste (care contorizeaza de cate ori a trecut programul pe acolo). Testarea rezolvarii se va face prin apelul predicatului afiseaza_cifre.

    Atentie, desi poate nu veti intelege inca ce face codul din interiorul predicatelor folosite pentru numararea testelor, pe voi va intereseaza acum doar cum sa le utilizati in rezolvare:

    • init_teste - initializeaza contorul pentru teste. Se apeleaza obligatoriu la inceputul predicatului cifre_cons
    • numara_teste - numara testele. Se apeleaza inaintea fiecarui test din cadrul lui cifre_cons (asa cum se vede in codul dat ca exemplu).
    • afiseaza_teste - afiseaza contorul (numarul de teste efectuate). Se apeleaza obligatoriu la finalul predicatului cifre_cons.
    cifra(0).
    cifra(1).
    cifra(2).
    cifra(3).
    cifra(4).
    cifra(5).
    cifra(6).
    cifra(7).
    cifra(8).
    cifra(9).

    init_teste:- retractall(nr_teste(_)).
    numara_teste:- retract(nr_teste(NV)) -> NN is NV+1, assert(nr_teste(NN)); assert(nr_teste(1)).
    afiseaza_teste:- nr_teste(N), format('Numar total teste ~d \n',[N]).

    cifre_cons(cifre(C1, C2, C3)):-init_teste,
                                                                numara_teste,cifra(C1),
                                                                numara_teste,cifra(C2),
                                                                numara_teste,cifra(C3),
                                                                numara_teste,C1=:=C2-1,
                                                                numara_teste,C2=:=C3-1,
                                                                numara_teste,Sum is C1+C2+C3,
                                                                numara_teste,Sum mod 2 =:=0,
                                                                afiseaza_teste.
                                                                
    afiseaza_cifre:- cifre_cons(C),write(C),nl,nl,fail;true.
    Predicatul afiseaza_cifre initial va avea ca output: | ?- afiseaza_cifre.
    Numar total teste 158
    cifre(1,2,3)

    Numar total teste 430
    cifre(3,4,5)

    Numar total teste 702
    cifre(5,6,7)

    Numar total teste 974
    cifre(7,8,9)

    yes
    | ?-

    Practic inaintea fiecarei solutii este afisat numarul de teste efectuat pentru a obtine acea solutie. Ce aveti de facut este sa reordonati sau sa comprimati testele din echipa astfel incat sa obtineti un numar cat mai mic de teste.

  2. In acest exercitiu va trebui sa corectati predicatul cercuri(-Cerc1, -Cerc2, -Cerc3) si, eventual, alte predicate auxiliare. Acesta doreste sa creeze asezari de cate exact 3 cercuri concentrice (de la Cerc1 - cel mai in interior pana la Cerc3, cel din exterior) cu urmatoarele proprietati:
    • distanta dintre doua cercuri (diferenta razelor) trebuie sa se regaseasca in lista de distante admise.
    • Culorile cercurilor sa fie "in armonie", cu alte cuvinte orice cerc C1 care cuprinde un cerc C2 trebuie sa aiba culoarea cu un numar asociat mai mare, decat numarul asociat culorii cercului interior.
    culoare(0,rosu).
    culoare(1,oranj).
    culoare(2,galben).
    culoare(3,verde).
    culoare(4,albastru).
    culoare(5,indigo).
    culoare(6,violet).

    %cerc(nume, raza, culoare)
    cerc(c1, 4, verde).
    cerc(c2, 10, verde).
    cerc(c3, 7, indigo).
    cerc(c4, 8, violet).
    cerc(c5, 5, albastru).
    cerc(c6, 20, indigo).
    cerc(c7, 7, oranj).
    cerc(c8, 2, galben).

    distante_admise([3, 2, 10]).

    cercuri(Cerc1, Cerc2, Cerc3):-     culoare(Poz1,Cl1)< culoare(Poz2,Cl2), culoare(Poz2,Cl2)< culoare(Poz3,Cl3), cerc(Cerc1, R1, Cl1), cerc(Cerc2, R2, Cl2), cerc(Cerc3, R3, Cl3), R1=<R2, R2=<R3, D1 is R2-R1,D2 is R3 - R2, distante_admise(list_dist), member(R2-R1, list_dist), member(R3-R2, list_dist).

    Predicatul cercuri ar trebui sa aiba outputul:

    | ?- cercuri(C1, C2, C3).
    C1 = c7,
    C2 = c2,
    C3 = c6 ? ;
    C1 = c8,
    C2 = c1,
    C3 = c3 ? ;
    C1 = c8,
    C2 = c5,
    C3 = c3 ? ;
    C1 = c8,
    C2 = c5,
    C3 = c4 ? ;
    no
    | ?-
  3. Se considera faptele: cuvant(abc).
    cuvant(abfgh).
    cuvant(dududu).
    cuvant(123).
    cuvant('+bubu').
    cuvant(lala).
    cuvant(lalila).
    cuvant(40).
    cuvant(abab).
    Sa se scrie un predicat fara parametri, afis_cns_v, care parcurge faptele de tip cuvant(...) si afiseaza doar atomii care incep cu o litera. Fiecare atom va fi precedat de sirul 'vocala:' sau 'consoana:' in functie de tipul primei litere. Exemplu: | ?- afis_cns_v.
    vocala:abc
    vocala:abfgh
    consoana:dududu
    consoana:lala
    consoana:lalila
    vocala:abab
    yes
    | ?-
  4. Se da urmatoarea baza de cunostinte: grup(g1, exp(e1,2+3-7), exp(e2,3+5+1)).
    grup(g2, exp(e3,5-2-2), exp(e4,1+1-1)).
    grup(g3, exp(e5,7-2), exp(e6,5-2-1)).
    grup(g4, exp(e7,3+4-0), exp(e8,7)).
    grup(g5, exp(e11,3-11+1), exp(e10,2+3+3)).
    grup(g6, exp(e12,2+3), exp(e13,1+1+1)).
    grup(g7, exp(e13,1-1), exp(e14,1+1+1)).
    Sa se rezolve subpunctele:
    1. un predicat care da ca solutii, pe rand, grupurile cu expresiile de aceeasi paritate: aceeasi_paritate(-G) | ?- aceeasi_paritate(G).
      G = g2 ? ;
      G = g4 ? ;
      G = g6 ? ;
      no
    2. un predicat care da ca solutii, pe rand, grupurile cu prima expresie cu un numar de operanzi mai mic decat a doua expresie (expresiile pot avea maxim 3 operanzi): gr_nr_op(-G). | ?- gr_nr_op(G).
      G = g3 ? ;
      G = g6 ? ;
      G = g7 ? ;
      no
      | ?-
    3. un predicat care da ca solutii toate perechiile de grupuri G1, G2, distincte, cu proprietatea ca daca avem S1 ca fiind suma expresiilor de pe pozitia 1 din G1 si G2, iar S2 suma expresiilor de pe pozitia 2, atunci S1< S2. Rezultatele se vor da sub forma rez(grupuri(G1,G2), sum_exp(S1, S2)). | ?- per(P).
      P = rez(grupuri(g1,g2),sum_exp(-1,10)) ? ;
      P = rez(grupuri(g1,g3),sum_exp(3,11)) ? ;
      P = rez(grupuri(g1,g4),sum_exp(5,16)) ? ;
      P = rez(grupuri(g1,g5),sum_exp(-9,17)) ? ;
      P = rez(grupuri(g1,g6),sum_exp(3,12)) ? ;
      P = rez(grupuri(g1,g7),sum_exp(-3,12)) ? ;
      P = rez(grupuri(g2,g1),sum_exp(-1,10)) ? ;
      P = rez(grupuri(g2,g5),sum_exp(-6,9)) ? ;
      P = rez(grupuri(g2,g7),sum_exp(0,4)) ? ;
      P = rez(grupuri(g3,g1),sum_exp(3,11)) ? ;
      P = rez(grupuri(g3,g5),sum_exp(-2,10)) ? ;
      P = rez(grupuri(g3,g7),sum_exp(4,5)) ? ;
      P = rez(grupuri(g4,g1),sum_exp(5,16)) ? ;
      P = rez(grupuri(g4,g5),sum_exp(0,15)) ? ;
      P = rez(grupuri(g4,g7),sum_exp(6,10)) ? ;
      P = rez(grupuri(g5,g1),sum_exp(-9,17)) ? ;
      P = rez(grupuri(g5,g2),sum_exp(-6,9)) ? ;
      P = rez(grupuri(g5,g3),sum_exp(-2,10)) ? ;
      P = rez(grupuri(g5,g4),sum_exp(0,15)) ? ;
      P = rez(grupuri(g5,g6),sum_exp(-2,11)) ? ;
      P = rez(grupuri(g5,g7),sum_exp(-8,11)) ? ;
      P = rez(grupuri(g6,g1),sum_exp(3,12)) ? ;
      P = rez(grupuri(g6,g5),sum_exp(-2,11)) ? ;
      P = rez(grupuri(g6,g7),sum_exp(4,6)) ? ;
      P = rez(grupuri(g7,g1),sum_exp(-3,12)) ? ;
      P = rez(grupuri(g7,g2),sum_exp(0,4)) ? ;
      P = rez(grupuri(g7,g3),sum_exp(4,5)) ? ;
      P = rez(grupuri(g7,g4),sum_exp(6,10)) ? ;
      P = rez(grupuri(g7,g5),sum_exp(-8,11)) ? ;
      P = rez(grupuri(g7,g6),sum_exp(4,6)) ? ;
      no
      | ?-  
    4. un predicat care da ca solutii toate perechiile de expresii din grupuri diferite, cu proprietatea ca modulul produsului expresiilor e mai mic decat un numar dat, Nr. Forma predicatului va fi: per_expresii(+Nr,-Rez). Rezultatul se va da sub forma rez(produs(Grup1/NumeExp1,Grup2/NumeExp2),exp(Exp1) * exp(Exp2)= Produs). Exemplu de output: | ?- per_expresii(5,Rez).
      Rez = rez(produs(g1/e1,g2/e3),exp(2+3-7)*exp(5-2-2)= -2) ? ;
      Rez = rez(produs(g1/e1,g2/e4),exp(2+3-7)*exp(1+1-1)= -2) ? ;
      Rez = rez(produs(g1/e1,g3/e6),exp(2+3-7)*exp(5-2-1)= -4) ? ;
      Rez = rez(produs(g1/e1,g7/e13),exp(2+3-7)*exp(1-1-1)=2) ? ;
      Rez = rez(produs(g2/e3,g3/e6),exp(5-2-2)*exp(5-2-1)=2) ? ;
      Rez = rez(produs(g2/e4,g3/e6),exp(1+1-1)*exp(5-2-1)=2) ? ;
      Rez = rez(produs(g2/e3,g6/e13),exp(5-2-2)*exp(1+1+1)=3) ? ;
      Rez = rez(produs(g2/e4,g6/e13),exp(1+1-1)*exp(1+1+1)=3) ? ;
      Rez = rez(produs(g2/e3,g7/e14),exp(5-2-2)*exp(1+1+1)=3) ? ;
      Rez = rez(produs(g2/e4,g7/e14),exp(1+1-1)*exp(1+1+1)=3) ? ;
      Rez = rez(produs(g7/e13,g2/e3),exp(1-1-1)*exp(5-2-2)= -1) ? ;
      Rez = rez(produs(g7/e13,g2/e4),exp(1-1-1)*exp(1+1-1)= -1) ? ;
      Rez = rez(produs(g7/e13,g3/e6),exp(1-1-1)*exp(5-2-1)= -2) ? ;
      Rez = rez(produs(g7/e13,g6/e13),exp(1-1-1)*exp(1+1+1)= -3) ? ;
      no
      | ?-

Nr. 4

  1. Optimizati predicatul echipa(-P). Predicatul echipa(-P) construieste echipele de cate 2 elevi (evident diferiti), care au notele mai mari ca 5 si media notelor lor mai mare ca 7. Echipele sunt de forma echipa(e1(Nume1,Prenume1),e2(Nume2, Prenume2), Medie). In rezolvare, fiecare test din predicat ar trebui pus pe o linie noua (pentru o citire mai usoara), fiind precedat mereu de apelul predicatului numara_teste (care contorizeaza de cate ori a trecut programul pe acolo). Testarea rezolvarii se va face prin apelul predicatului afiseaza_echipe.

    Atentie, desi poate nu veti intelege inca ce face codul din interiorul predicatelor folosite pentru numararea testelor, pe voi va intereseaza acum doar cum sa le utilizati in rezolvare:

    • init_teste - initializeaza contorul pentru teste. Se apeleaza obligatoriu la inceputul predicatului echipa
    • numara_teste - numara testele. Se apeleaza inaintea fiecarui test din cadrul lui echipa (asa cum se vede in codul dat ca exemplu).
    • afiseaza_teste - afiseaza contorul (numarul de teste efectuate). Se apeleaza obligatoriu la finalul predicatului echipa.
    /*predicate pentru numararea testelor */
    init_teste:- retractall(nr_teste(_)).
    numara_teste:- retract(nr_teste(NV)) -> NN is NV+1, assert(nr_teste(NN)); assert(nr_teste(1)).
    afiseaza_teste:- nr_teste(N), format('Numar total teste ~d \n',[N]).


    %elev(nume, prenume, nota)
    elev('Popescu','Ion',7).
    elev('Dorel','Doru', absent).
    elev('Georgescu','Gigel',10).
    elev('Danescu','Ion',4).
    elev('Tache','Lulu',4).
    elev('Costache','Costin',8).
    elev('Marinescu','Maria',5).
    elev('Petrescu','Petre', absent).
    elev('Gogulescu','Gogu',3).


    echipa(Ech):-
        init_teste,
        numara_teste, elev(Nume1, Prenume1, Nota1),
        numara_teste, elev(Nume2, Prenume2, Nota2),
        numara_teste, Nume1 \== Nume2,
        numara_teste, Prenume1 \== Prenume2,
        numara_teste, number(Nota1),
        numara_teste, number(Nota2),
        numara_teste, Medie is (Nota1+Nota2)/2,
        numara_teste, Nota1>=5,
        numara_teste, Nota2>=5,
        numara_teste, Ech = echipa(e1(Nume1,Prenume1),e2(Nume2, Prenume2), Medie),
        numara_teste, Medie>=7,
        afiseaza_teste.
        


    afiseaza_echipe:- echipa(Ech),write(Ech),nl,nl,fail;true.

    Predicatul afiseaza_echipe initial va avea ca output: | ?- afiseaza_echipe.
    Numar total teste 16
    echipa(e1(Popescu,Ion),e2(Georgescu,Gigel),8.5)

    Numar total teste 34
    echipa(e1(Popescu,Ion),e2(Costache,Costin),7.5)

    Numar total teste 90
    echipa(e1(Georgescu,Gigel),e2(Popescu,Ion),8.5)

    Numar total teste 118
    echipa(e1(Georgescu,Gigel),e2(Costache,Costin),9.0)

    Numar total teste 127
    echipa(e1(Georgescu,Gigel),e2(Marinescu,Maria),7.5)

    Numar total teste 236
    echipa(e1(Costache,Costin),e2(Popescu,Ion),7.5)

    Numar total teste 249
    echipa(e1(Costache,Costin),e2(Georgescu,Gigel),9.0)

    Numar total teste 307
    echipa(e1(Marinescu,Maria),e2(Georgescu,Gigel),7.5)

    yes
    | ?-

    Practic inaintea fiecarei solutii este afisat numarul de teste efectuat pentru a obtine acea solutie. Ce aveti de facut este sa reordonati sau sa comprimati testele din echipa astfel incat sa obtineti un numar cat mai mic de teste.

  2. In acest exercitiu va trebui sa corectati predicatul asezare(-Cub1, -Cub2, -Cub3) si, eventual, alte predicate auxiliare. Acesta doreste sa creeze asezari orizontale de cate exact 3 cuburi cu urmaoarele proprietati:
    • masa totala a cuburilor (suma kilogramelor) sa nu depaseasca valoarea din greutate_max.
    • diferenta de inaltime dintre doua cuburi consecutive trebuie sa se regaseasca in lista de inaltimi admise.
    • cuburile in asezare trebuie sa fie diferite intre ele
    diferente_admise([10, 40]).
    %cub(nume, latura, greutate).
    cub(a,10,3).
    cub(b,30,20).
    cub(c,5,5).
    cub(d,8,10).
    cub(e,4,1).
    cub(f,10,3).
    cub(g,50,5).
    cub(h,20,11).
    cub(i,40,18).
    greutate_max(20).

    diferenta_inalt(x,y,abs(x-y)).

    asezare(Cub1, Cub2, Cub3):- Cub1 =\= Cub2,Cub2 =\= Cub3,   cub(Cub1, D1, G1), cub(Cub2, D2, G2), cub(Cub3, D3, G3), diferente_admise(Ld),diferenta_inalt(D1,D2,Dif),member( Dif, Ld),diferenta_inalt(D2,D3,Dif),member(Dif, Ld), G1+G2+G3 < greutate_max(g).

    Predicatul asezare ar trebui sa aiba outputul:

    | ?- asezare_corectat(Cub1, Cub2, Cub3).
    Cub1 = a,
    Cub2 = g,
    Cub3 = f ? ;
    Cub1 = a,
    Cub2 = h,
    Cub3 = f ? ;
    Cub1 = f,
    Cub2 = g,
    Cub3 = a ? ;
    Cub1 = f,
    Cub2 = h,
    Cub3 = a ? ;
    Cub1 = g,
    Cub2 = a,
    Cub3 = h ? ;
    Cub1 = g,
    Cub2 = f,
    Cub3 = h ? ;
    Cub1 = h,
    Cub2 = a,
    Cub3 = g ? ;
    Cub1 = h,
    Cub2 = f,
    Cub3 = g ? ;
    no
  3. Se considera faptele: cuvant(abc).
    cuvant(abfgh).
    cuvant(dududu).
    cuvant(lala).
    cuvant(lalila).
    cuvant(abab).
    Sa se scrie un predicat fara parametri, afis_per_cuv, care afiseaza toate perechiile de cuvinte care incep cu aceleasi doua litere fie in ordinea in care apar in primul cuvant, fie inversate (de exemplu, daca un cuvant incepe cu ab, celalalt poate incepe cu ab sau cu ba). Perechiile se vor afisa cate una pe un rand, cuvintele fiind separate prin - (minus). Perechiile se pot repeta, in sensul ca daca a fost afisata o pereche de forma cuv1-cuv2, e ok sa se afiseze si cuv2-cuv1. Exemplu: | ?- afis_per_cuv.
    abc-abfgh
    abc-abab
    abfgh-abc
    abfgh-abab
    lala-lalila
    lalila-lala
    abab-abc
    abab-abfgh
    yes
    | ?-
  4. Se da urmatoarea baza de cunostinte: grup(g1, exp(e1,2+3-7), exp(e2,3+5+1)).
    grup(g2, exp(e3,5-2-2), exp(e4,1+1-1)).
    grup(g3, exp(e5,7-2), exp(e6,5-2-1)).
    grup(g4, exp(e7,3+4-0), exp(e8,7)).
    grup(g5, exp(e11,3-11+1), exp(e10,2+3+3)).
    grup(g6, exp(e12,2+3), exp(e13,1+1+1)).
    grup(g7, exp(e13,1-1-1), exp(e14,1+1+1)).
    Sa se rezolve subpunctele:
    1. un predicat care da ca solutii, pe rand, grupurile cu prima expresie mai mica decat N si a doua mai mare: compar_N(+N,-G) | ?- compar_N(0, G).
      G = g1 ? ;
      G = g5 ? ;
      G = g7 ? ;
      no
    2. un predicat care da ca solutii, pe rand, grupurile care au minim o expresie (cu 3 operanzi) cu toti operanzii egali : egal_op(-G). | ?- egal_op(G).
      G = g2 ? ;
      G = g6 ? ;
      G = g7 ? ;
      no
      | ?-
    3. un predicat care da ca solutii toate perechiile de grupuri G1, G2, diferite, cu proprietatea ca mediile expresiilor lor sunt egale. Rezultatele se vor da sub forma pereche(med(G1,S1),med(G2,S2)). | ?- per(G).
      G = pereche(med(g1,3.5),med(g3,3.5)) ? ;
      G = pereche(med(g2,1.0),med(g7,1.0)) ? ;
      G = pereche(med(g3,3.5),med(g1,3.5)) ? ;
      G = pereche(med(g7,1.0),med(g2,1.0)) ? ;
      no
      | ?-
    4. un predicat care da ca solutii toate perechiile de expresii din grupuri diferite, cu proprietatea ca prima expresie are rezultatul mai mic decat rezultatul celei de-a doua si rezultatele au aceeasi paritate. Rezultatul se va da sub forma rez(NumeExp1/Grup1+NumeExp2/Grup2=(Exp1)+(Exp2), nul) rez(NumeExp1-Grup1<NumeExp1-Grup1,adica(Rez1<Rez2)). Iata primele solutii (sunt foarte multe asa ca nu le-am pus pe toate): | ?- per_expresii(P).
      P = rez(e3-g1<e4-g2,adica(-1<1)) ? ;
      P = rez(e3-g1<e5-g2,adica(-1<1)) ? ;
      P = rez(e3-g1<e6-g2,adica(-1<1)) ? ;
      P = rez(e1-g1<e8-g3,adica(-2<2)) ? ;
      P = rez(e3-g1<e7-g3,adica(-1<5)) ? ;
      P = rez(e3-g1<e10-g4,adica(-1<7)) ? ;
      P = rez(e3-g1<e11-g4,adica(-1<7)) ? ;
      P = rez(e3-g1<e12-g4,adica(-1<7)) ? ;
      P = rez(e1-g1<e14-g5,adica(-2<8)) ? ;
      P = rez(e1-g1<e15-g5,adica(-2<8)) ? ;
      P = rez(e1-g1<e18-g6,adica(-2<8)) ?
      yes
      | ?-