Cod sursa(job #1067229)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 26 decembrie 2013 16:13:59
Problema Bool Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.78 kb
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>

#include <vector>
#include <map>

#define CONST 0
#define VAR 1
#define OPERATOR 2
#define NOT 3
#define OR 4
#define AND 5

using namespace std;

std::map<int, bool> truth_table;

struct Node {
  int type;
  int val;

  Node* left;
  Node* right;

  Node(int type, int val, Node* left, Node* right) : type(type), val(val),
    left(left), right(right) {}
};

bool eval(Node* root) {
  switch (root->type) {
    case CONST:
      return root->val;
    case VAR:
      return truth_table[root->val];
    case OPERATOR:
      switch (root->val) {
        case NOT:
          return !eval(root->right);
        case AND:
          return eval(root->left) && eval(root->right);
        case OR:
          return eval(root->left) || eval(root->right);
        default:
          std::cerr << "Unknown operator!" << std::endl;
      }
    default:
      std::cerr << "Unknown node typ!" << std::endl;
  }
}

int get_priority(std::string& token) {
  if (token == "NOT") {
    return 3;
  } else if (token == "AND") {
    return 2;
  } else if (token == "OR") {
    return 1;
  }
}

int get_operator(std::string& token) {
  if (token == "NOT") {
    return NOT;
  } else if (token == "AND") {
    return AND;
  } else if (token == "OR") {
    return OR;
  }
}

Node* rparse(std::vector<string>& tokens, int first, int last) {
  if (first > last) {
    return NULL;
  } else if (first == last) {
    // Base case.
    if (tokens[first] == "TRUE" || tokens[first] == "FALSE") {
      return new Node(CONST, (tokens[first] == "TRUE") ? 1 : 0, NULL, NULL);
    } else if (tokens[first].size() == 1) {
      return new Node(VAR, tokens[first][0], NULL, NULL);
    } else {
      std::cerr << "Wrong parse tree!" << std::endl;
      exit(1);
    }
  } else {
    // Find the least priority operator outside all parantheses.
    int index = -1;
    int priority = -1;
    int nopen = 0;
    for (int i = first; i <= last; ++i) {
      if (tokens[i] == "(") {
        nopen++;
      } else if (tokens[i] == ")") {
        nopen--;
      } else if (tokens[i] == "NOT" ||
                 tokens[i] == "AND" ||
                 tokens[i] == "OR") {
        if (nopen == 0 && (priority == -1 ||
                           priority > get_priority(tokens[i]))) {
          index = i;
          priority = get_priority(tokens[i]);
        }
      }
    }

    if (index == -1) {
      return rparse(tokens, first + 1, last - 1);
    }

    return new Node(OPERATOR,
                    get_operator(tokens[index]),
                    rparse(tokens, first, index - 1),
                    rparse(tokens, index + 1, last));
  }
}

Node* parse(std::string& nline) {
  // Create a new line in which you insert space before and after each
  // paranthesis.
  std::string line;
  for (int i = 0; i < nline.size(); ++i) {
    if (nline[i] == ')' || nline[i] == '(') {
      line.append(" ").append(std::string(1, nline[i])).append(" ");
    } else {
      line.append(std::string(1, nline[i]));
    }
  }

  // Break the line into tokens.
  std::vector<string> tokens;
  char* buffer = strdup(line.c_str());
  for (char* p = strtok(buffer, " \t\n"); p; p = strtok(NULL, " \t\n")) {
    if (*p) {
      tokens.push_back(std::string(p));
    }
  }
  delete buffer;

  // Recursively parse the tokens.
  return rparse(tokens, 0, tokens.size() - 1);
}

void dump_tree(Node* root) {
  switch (root->type) {
    case CONST:
      if (root->val) {
        std::cerr << " 1 ";
      } else {
        std::cerr << " 0 ";
      }
      break;
    case VAR:
      std::cerr << " " << ((char)root->val) << " ";
      break;
    case OPERATOR:
      if (root->val == NOT) {
        std::cerr << " ! (";
        dump_tree(root->right);
        std::cerr << ")";
      } else if (root->val == AND) {
        std::cerr << "(";
        dump_tree(root->left);
        std::cerr << ") && (";
        dump_tree(root->right);
        std::cerr << ")";
      } else if (root->val == OR) {
        std::cerr << "(";
        dump_tree(root->left);
        std::cerr << ") || (";
        dump_tree(root->right);
        std::cerr << ")";
      }
      break;
  }
}

int main()
{
  std::ifstream in("bool.in");
  std::ofstream out("bool.out");

  std::string line;
  std::getline(in, line);

  // Parse the boolean expression.
  Node* expr = parse(line);

/*  std::cerr << line << std::endl;
  dump_tree(expr);
  std::cerr << std::endl; */

  int n;
  in >> n;

  std::string vars;
  in >> vars;

  // Initialize the truth table.
  for (int var = 'A'; var <= 'Z'; ++var) {
    truth_table[var] = false;
  }

  // Run the evaluation.
  for (int i = 0; i < vars.size(); ++i) {
    truth_table[vars[i]] = !truth_table[vars[i]];
    if (eval(expr)) {
      out << "1";
    } else {
      out << "0";
    }
  }

  out << std::endl;

  in.close();
  out.close();

  return 0;
}