Cod sursa(job #1823082)

Utilizator alexnekiNechifor Alexandru alexneki Data 5 decembrie 2016 21:51:32
Problema Bool Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.12 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) {
  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 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) evaltree(root);
  }
  out<<endl;
  return 0;
}