Cod sursa(job #1840241)

Utilizator alexnekiNechifor Alexandru alexneki Data 3 ianuarie 2017 23:34:03
Problema Bool Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.08 kb
//Bool cu arbori de derivare
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <cassert>

using namespace std;

ifstream in("bool.in");
ofstream out("bool.out");


int const prmax = 3; //number of priority levels of the operators
int const nmax = 1001;


map<string, char> f;
map<char, int> prio;
map<char, bool> value;


struct tree {
    char val;
    tree *left;
    tree *right;
};
tree *root;


int n;
char ex[nmax]; //expression to be evaluated
char line[nmax];
char word[nmax];
void read() {
  f["NOT"] = '!';
  f["AND"] = '&';
  f["OR"] = '|';
  f["TRUE"] = '1';
  f["FALSE"] = '2';

  prio['|'] = 0;
  prio['&'] = 1;
  prio['!'] = 2;

  in.getline(line, nmax);

  int wordp = 0, exp = 0; //pointers in word and expression
  int i = 0;
  while (line[i] != '\0') {
    if (line[i] == ' ' || line[i] == '(' || line[i] == ')') {

      //add word from stack first
      if (0 < wordp) {
        if (1 < wordp) { //special word
          word[wordp] = '\0'; //end word
          ex[exp] = f[word];
        } else { //just a letter
          ex[exp] = word[0];
          value[word[0]] = false;
        }
        wordp = 0; //clear stack
        exp++;
      }

      //then add the bracket, or just ignore the white space
      if (line[i] == '(' || line[i] == ')') {
        ex[exp] = line[i];
        exp++;
      }
    } else {
      word[wordp] = line[i];
      wordp++;
    }
    i++;
  }
  if (0 < wordp) {
    if (1 < wordp) { //special word
      word[wordp] = '\0'; //end word
      ex[exp] = f[word];
    } else { //just a letter
      ex[exp] = word[0];
      value[word[0]] = false;
    }
    wordp = 0; //clear word
    exp++;
  }
  ex[exp] = '\0'; //end expression
  value['1'] = true; //everything else is false in the beginning

  n = exp;
}


int prevop[prmax][nmax];
int lastvisited[prmax][nmax];

void precompute() {
  //daca nu merge pun lastvisited afara
  //lastvisited[prioritate][nestinglevel]
  //daca parcurg de la stanga la dreapta => pot sa updatez: prevop
  for(int i=0; i<n; i++) {
    for(int k=0; k<prmax; k++) {
      lastvisited[k][i] = -1;
    }
  }


  int nestinglevel = 0;
  //O(n)
  for(int i = 0 ; i < n ; i++){ //1+2+3+4
    if(ex[i] == '(') {//1+(2+3)
      for(int k = 0 ; k < prmax ; k++){
        prevop[k][i] = lastvisited[k][nestinglevel];
      }
      nestinglevel++;
    } else if(ex[i] == ')') {
      nestinglevel--; //2+(3-4)+5
      for(int k = 0 ; k < prmax ; k++){
        prevop[k][i] = lastvisited[k][nestinglevel];
      }
    } else {
      for(int k = 0 ; k < prmax ; k++){
        prevop[k][i] = lastvisited[k][nestinglevel];
      }
//      if(!(ex[i]=='1' || ex[i] == '0' || (ex[i]>='A' && ex[i] <='Z')))
      if(!(prio.find(ex[j]) == prio.end()))
        lastvisited[prio[ex[i]]][nestinglevel] =  i;
    }
  }
}


tree* buildtree(int from, int to) { //1 A B 0
  //(1|2)&(3|4)
  tree *result = nullptr;;
//1 +2 +(3 +4)+5
  if(prevop[0][to] < from && prevop[1][to] < from && prevop[2][to] < from && from != to) {
    result = buildtree(from + 1, to - 1);
  } else if(from == to){
    result = new tree(); // 10001 - 20001; 10001 - 15001; 17345 -> result
    result->val = ex[from];
    result->left = nullptr;
    result->right = nullptr;
    //cout<<":";
  } else {
    if(from <= prevop[0][to]){ ///1+2+(3+4)+5
      ///il luam
      result = new tree(); /// 10001 - 20001; 10001 - 15001; 17345 -> result
      result->val = ex[prevop[0][to]];
      ///il despartim
      result->left = buildtree(from, prevop[0][to]-1); //3+5
      //cout<<":";
      result->right = buildtree(prevop[0][to]+1 ,to);
      //cout<<"|";
    } else if(from <= prevop[1][to]){
      ///il luam
      result = new tree(); /// 10001 - 20001; 10001 - 15001; 17345 -> result
      result->val = ex[prevop[1][to]];
      ///il despartim
      // cout<<"->("<<from<<", "<<to<<")"<<endl;

      // cout<<from<<" "<<prevop[1][to]-1<<endl;
      result->left = buildtree(from, prevop[1][to]-1); //3+5
      //cout<<prevop[1][to]+1<<" "<<to<<endl;
      result->right = buildtree(prevop[1][to]+1 ,to);
    } else if (from <= prevop[2][to]) { //avem !!!A
      // cout<<ex[from]<<" "<<from<<" "<<to<<'\n';
      assert(ex[from] == '!');
      result = new tree(); // 10001 - 20001; 10001 - 15001; 17345 -> result
      result->val = ex[from];
      result->left = nullptr;
      result->right = buildtree(from + 1 ,to);
    } else
      while(true);
  }
  return result;
}

bool eval(tree *node){ //O(n)
  if(node->val == '&') {
    return eval(node->left) & eval(node->right);
  } else if(node->val == '|') {
    return eval(node->left) | eval(node->right);
  } else if(node->val == '!'){
    return !eval(node->right);
  } else {
    return value[node->val];
  }
}


int main() {
  read(); //A&B|C|!D|(1&0)
  precompute();
  root = buildtree(0, n - 1); //0
  //citire
  int ntest;
  in >>ntest;
  char c;
  for(int i = 0 ; i < ntest ; i++){
    in>>c;
    value[c] = !value[c];
    out<<(int)eval(root);
  }
  return 0;
}