Cod sursa(job #2314548)

Utilizator mariusmagureanmagurean marius mariusmagurean Data 8 ianuarie 2019 18:38:45
Problema Evaluarea unei expresii Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.45 kb
/*problema evaluare de pe infoarena, evaluarea unei expresii aritmetice
reprezentam expresia cu un arbore binar folosit ptr forma poloneza,
unde operatorii sunt pe noduri interioare, iar operanzii pe frunze
evit recursivitatea indirecta si folosesc metoda cu prioritati ale operatorilor
operatorii - si + au, initial,  prioritatea 1, iar * si / 10.
Aparitia unei paranteze rotunde, creste prioritatea operatorilor ce urmeaza cu 10, iar una inchisa, scade cu 10
Prioritatea unui operand este 100005
Parantezele nu au pondere si sunt excluse in vectorul pond
Retin prioritatile in vectorul pond
Arborele va fi retinut dinamic, fiecare nod avand informatia (operand sau operator) si doua campuri de adresa,
ptr fiul stang si ptr cel drept.
Limita de valori ptr operanzi este 1 000 000 000
vom lua 1 000 000 001 ca fiind +, 1 000 000 002, drept -, 1 000 000 003 *, 1 000 000 004 /
Sirul initial se va prelucra intr-un vector nou, numit nou, ce va retine operatorii ca si intregii de mai sus si operanzii
In acelasi timp cu constructia vectorului de mai sus, se va construi si vectorul de prioritati
Alegerea nodului curent din arbore se face astfel:
    Se foloseste divide et impera
    Cautarea incepe cu limitele 0 si ultima componenta a vectorului de ponderi
    Se cauta cea mai mica pondere intre aceste limite(pozitia poz) si se completeaza informatia cu acel caracter
        Daca limita inferioara coincide cu cea superioara am dat de o frunza si se completeaza cu null campurile de adresa
        Altfel, fiul stang va fi nodul rezultat in urma apelului cu 1, poz-1, iar fiul drept ce rezulta in urma apelului (poz+1, ls)
Functia va intoarce nodul astfel construit, prn urmare, in final, va returna adresa radacinii arborelui
Daca vrem forma poloneza prefixata a expresiei, vom folosi o parcurgere radacina stanga dreapta, iar daca vrem cea postfixata,
stanga dreapta radacina

Evaluarea expresiei se va face tot dupa tehnica Divide et Impera
    Daca nodul nu este terminal se retine valoarea returnata de apelul cu fiul stang si cea rezultata de la fiul drept
    si apoi se aplica operatorul continut de csmpul informatie
    contrar, se intoarce operandul


*/
#include <fstream>
#define dim 100005
#define plus 1000000001
#define minus 1000000002
#define ori 1000000003
#define div 1000000004
using namespace std;

char sir[dim];
int pond[dim];
int nou[dim];
struct nod
{
    int info;
    nod* stg;
    nod *drp;
};

nod * generare(int li, int ls)
{
    nod* rez;
    int minim,poz,i;
    //parcurgem vectorul de ponderi de la dreapta la stanga si retinem in poz, pozitia ponderii celei mai mici
    minim=pond[ls];
    poz=ls;
    for(i=ls-1;i>=li;i--)
        if(pond[i]<minim)
        {
            minim=pond[i];
            poz=i;
        }
    //aloc dinamic nodul pe care il voi adauga in arbore si completez campurile
    rez=new nod;
    rez->info=nou[poz];
    if(li==ls)
    {
        rez->stg=NULL;
        rez->drp=NULL;
    }
    else
    {
        rez->stg=generare(li,poz-1);
        rez->drp=generare(poz+1,ls);
    }
    return rez;
}

int evaluare(nod*rad)
{
    switch(rad->info)
    {
        case plus: return evaluare(rad->stg)+evaluare(rad->drp);break;
        case minus: return evaluare(rad->stg)-evaluare(rad->drp);break;
        case ori: return evaluare(rad->stg)*evaluare(rad->drp);break;
        case div: return evaluare(rad->stg)/evaluare(rad->drp);break;
        default: return rad->info;
    }
}

int main()
{
    ifstream fin("evaluare.in");
    ofstream fout("evaluare.out");
    fin.get(sir, dim);
    int pondere=0,val;
    //construiesc vectorul de intregi si vectorul corespunzator de ponderi
    unsigned int i;
    int j=-1;
    for(i=0;sir[i]!=0;i++)
    {
        switch(sir[i])
        {
            case '(': pondere+=10;break;
            case ')': pondere-=10;break;
            case '+': nou[++j]=plus;pond[j]=pondere+1;break;
            case '-': nou[++j]=minus;pond[j]=pondere+1;break;
            case '*': nou[++j]=ori;pond[j]=pondere+10;break;
            case '/': nou[++j]=div;pond[j]=pondere+10;break;
            default:
                for(val=0;sir[i]>='0' && sir[i]<='9';i++)
                    val=val*10+(sir[i]-'0');
                i--;//i va pointa catre primul caracter non cifra si apoi cu i++ din for il va sari, decrementam
                nou[++j]=val;pond[j]=dim;
        }
    }
    nod*rad=generare(0,j);
    fout<<evaluare(rad);
    return 0;
}