Cod sursa(job #2471139)

Utilizator uvIanisUrsu Ianis Vlad uvIanis Data 10 octombrie 2019 13:23:12
Problema Bool Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.22 kb
#include <bits/stdc++.h>
#define L_MAX 1000
using namespace std;


//functie care returneaza TIPUL TEXTULUI care incepe cu pozitia "pos" in expresia "exp"
//și anume daca este operator, variabila, valoare de adevar, ... (in primul compartiment al perechii)
//precum și TEXTUL IN SINE (in al doilea compartiment al perechii)
pair<string, string> parser(string& exp, size_t pos)
{

    if(exp[pos] == '(') return make_pair("paranteza deschisa", "(");
    if(exp[pos] == ')') return make_pair("paranteza inchisa", ")");
    if(exp[pos] == ' ') return make_pair("spatiu liber", " ");
    if(exp[pos] == '\0') return make_pair("sfarsit", "\\0");


    string value("");

    while(exp[pos] != '(' && exp[pos] != ')' && exp[pos] != ' ' && exp[pos] != '\0')
    {
        value += exp[pos];
        ++pos;
    }

    if(value == "AND") return make_pair("operator", value);
    if(value == "NOT") return make_pair("operator", value);
    if(value == "OR") return make_pair("operator", value);

    if(value == "TRUE") return make_pair("valoare de adevar", value);
    if(value == "FALSE") return make_pair("valoare de adevar", value);

    if(value >= "A" && value <= "Z") return make_pair("variabila", value);


    return make_pair("-1", "-1");
}


//functie care returneaza pozitia unei majuscule in alfabet
//prima pozitie o consideram 0
inline size_t pozitie_litera(string& x)
{
    return x[0] - 'A';
}


//functie care returneaza prioritatea unui operator
//valorile sunt doar o conventie
size_t prioritate_operator(string& op)
{
    if(op == "NOT") return 3;
    if(op == "AND") return 2;
    if(op == "OR") return 1;

    return 0;   //pentru paranteza
}

//functie care evalueaza cea mai simpla expresie formata din doi operanzi si un operator
//B are o valoare implicita ca sa evitam precizarea lui in cazul operatorului NOT
size_t evalueaza_expresize_de_baza(string& op, bool A, bool B = false)
{
    if(op == "AND") return A & B;
    if(op == "OR") return A | B;

    return !A;
}


//functie care evalueaza o expresie care contine variabile
//evaluarea este identica cu a evaluarii unei expresii in forma invers poloneza
//dar nu o mai tranformam intr-o expresie invers poloneza ci o evaluam direct
bool evalueaza_expresie(string& expresie, vector<bool> valoareVariabila)
{
    vector<bool> stivaOperanzi;
    //nu il declar "stack" deoarece trebuie sa accesez și alte elemente expceptand varful

    stack<string> stivaOperatori;


    pair<string, string> text_curent;
    size_t i = 0;

    do{
         text_curent = parser(expresie, i);
        //extragem textul curent

        if(text_curent.first == "variabila")
        {
            stivaOperanzi.push_back(valoareVariabila[pozitie_litera(text_curent.second)]);
        }

        if(text_curent.first == "valoare de adevar")
        {
            if(text_curent.second == "TRUE" ) stivaOperanzi.push_back(true);
            else stivaOperanzi.push_back(false);
        }

        if(text_curent.first == "paranteza deschisa")
        {
            stivaOperatori.push(text_curent.second);
        }

        if(text_curent.first == "operator" || text_curent.first == "paranteza inchisa")
        {
            while(!stivaOperatori.empty() && stivaOperatori.top() != "(" && prioritate_operator(text_curent.second) <= prioritate_operator(stivaOperatori.top()))
            {
                if(stivaOperatori.top() == "NOT")
                {
                    if(text_curent.second == "NOT") break; //nu putem inca executa operatorul NOT
                    else stivaOperanzi[stivaOperanzi.size() - 1] = evalueaza_expresize_de_baza(stivaOperatori.top(), stivaOperanzi[stivaOperanzi.size() - 1]);

                }
                else
                {
                    stivaOperanzi[stivaOperanzi.size() - 2] = evalueaza_expresize_de_baza(stivaOperatori.top(), stivaOperanzi[stivaOperanzi.size() - 2], stivaOperanzi[stivaOperanzi.size() - 1]);
                    stivaOperanzi.pop_back();
                }

                stivaOperatori.pop();
            }

            if(text_curent.first == "paranteza inchisa") stivaOperatori.pop(); //eliminam paranteza deschisa
            else stivaOperatori.push(text_curent.second);
        }

        i = i + text_curent.second.size();
        //schimbam pozitia sarind peste textul curent

    } while(text_curent.first != "sfarsit");


    //golim operatorii ramasi in stiva
    while(!stivaOperatori.empty())
    {
        if(stivaOperatori.top() == "NOT")
        {
            stivaOperanzi[stivaOperanzi.size() - 1] = evalueaza_expresize_de_baza(stivaOperatori.top(), stivaOperanzi[stivaOperanzi.size() - 1]);
        }
        else
        {
            stivaOperanzi[stivaOperanzi.size() - 2] = evalueaza_expresize_de_baza(stivaOperatori.top(), stivaOperanzi[stivaOperanzi.size() - 2], stivaOperanzi[stivaOperanzi.size() - 1]);
            stivaOperanzi.pop_back();
        }

        stivaOperatori.pop();
    }

    //raspunsul cautat se va afla in ultimul operand ramas
    return stivaOperanzi[0];
}


int main()
{
    ifstream fin("bool.in");
    ofstream fout("bool.out");


    string expresie;
    //sir de caractere in care memoram expresia

    getline(fin, expresie);


   vector<bool> valoareVariabila(26)  ;
    //vector in care stocam valorile variabilelor problemei


    for(size_t i = 0; i < 26; ++i) valoareVariabila[i] = false;
    //din enunt, la inceput toate variabilele au valoarea false


    size_t N;
    //N-ul cu semnificatia din problema
    fin >> N;

    string c(" ");
    //variabila in care stocam, pe rand, cate un caracter de pe ultima linie
    //o folosim pentru a determina valoarea carei variabile se comuta
    //nu folosim char din cauza faptului ca toate functiile iau ca parametii string-uri
    //si programul e deja prea mare pentru funtion overload


    for(size_t i = 1; i <= N; ++i)
    {
        fin >> c[0];

        valoareVariabila[pozitie_litera(c)] = !valoareVariabila[pozitie_litera(c)];
        //comutam valoarea unei variabile

        fout << evalueaza_expresie(expresie, valoareVariabila);
        //evaluam expresia și afișam rezultatul in fișier
    }

    return 0;
}