Cod sursa(job #1840240)

Utilizator alexnekiNechifor Alexandru alexneki Data 3 ianuarie 2017 23:33:38
Problema Bool Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 7.3 kb
#include <iostream>
#include <fstream>
#include <map>
#include <cassert>

using namespace std;

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

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

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;
char ex[nmax]; //expression to be evaluated
int n; //number of elements in clean expression
tree *root; //binary tree corresponding to the given expression

int open[nmax], closed[nmax];
//when traversing the expression and reaching index i, open[i] & closed[i] = no. of open & closed brackets encountered so far

int nextop[prmax][nmax], prevop[prmax][nmax];

void read() {
  f["NOT"] = '!';
  f["AND"] = '&';
  f["OR"] = '|';
  f["TRUE"] = '1';
  f["FALSE"] = '2';

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

  char line[nmax];
  in.getline(line, nmax);

  char word[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 inc(int x, int from, int to) {
  return (from < to) ? (x + 1) : (x - 1);
}

bool inside(int x, int from, int to) {
  return (from < to) ? (x <= to) : (to <= x);
}

char openbr(int from, int to) {
  return (from < to) ? '(' : ')';
}

char closedbr(int from, int to) {
  return (from < to) ? ')' : '(';
}

void analyzeexpression(char *ex, int from, int to, int *open, int *closed, int prevop[prmax][nmax]) {
  int lastop[prmax][nmax];
  for (int i = 0; i < prmax; i++) {
    for (int j = 0; j < n; j++) {
      lastop[i][j] = -1;
      prevop[i][j] = -1;
      open[j] = closed[j] = 0;
    }
  }

  int j = from;
  while (inside(j, from, to)) {
    if (ex[j] == openbr(from, to)) {
      for (int i = 0; i < prmax; i++) {
        prevop[i][j] = lastop[i][open[j] - closed[j]];
      }
      open[j]++;
    } else if (ex[j] == closedbr(from, to)) {
      closed[j]++;
      for (int i = 0; i < prmax; i++) {
        prevop[i][j] = lastop[i][open[j] - closed[j]];
      }
    } else { //operator, character or a number
      for (int i = 0; i < prmax; i++) {
        prevop[i][j] = lastop[i][open[j] - closed[j]];
      }
      if (!(prio.find(ex[j]) == prio.end())) { //if an operator
        lastop[prio[ex[j]]][open[j] - closed[j]] = j;
      }
    }
    open[inc(j, from, to)] = open[j];
    closed[inc(j, from, to)] = closed[j];
    j = inc(j, from, to);
  }
}

bool hasbigbrackets(int from, int to) {
  bool result = false;
  if (ex[from] == '(' && ex[to] == ')' && (prevop[0][to] < 0 || prevop[0][to] < from)) {
    if (ex[from] != '!' && (nextop[1][from] < 0 || to < nextop[1][from])) {
      result = true;
    }
  }
  return result;
}

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;
}

/*
tree *buildtree(int from, int to) {
  tree *node;
  if (hasbigbrackets(from, to)) {
    node = buildtree(from + 1, to - 1);
  } else if (from == to) {
    node = new tree{
        ex[from],
        nullptr,
        nullptr};
  } else { //for sure I have an operator here
    if (from < prevop[0][to]) {
      node = new tree{
          ex[prevop[0][to]],
          buildtree(from, prevop[0][to] - 1),
          buildtree(prevop[0][to] + 1, to)};
    } else if (from < prevop[1][to]) {
      node = new tree{
          ex[prevop[1][to]],
          buildtree(from, prevop[1][to] - 1),
          buildtree(prevop[1][to] + 1, to)};
    } else if (ex[from] == '!') {
      node = new tree{
          ex[from],
          nullptr,
          buildtree(from + 1, to)
      };
    } else {
      while(true);
    }
  }
  return node;
}
*/

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];
  }
}

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

int main() {
  read();

  analyzeexpression(ex, 0, n - 1, open, closed, prevop);
  analyzeexpression(ex, n - 1, 0, open, closed, nextop);

  root = buildtree(0, n - 1);

  int nquery;
  in >> nquery;
  char letter;
  for (int i = 0; i < nquery; i++) {
    in >> letter;
    value[letter] = !value[letter];
    out << (int) eval(root);
  }
  out<<endl;
  return 0;
}