Cod sursa(job #227508)

Utilizator andrey932Andrei andrey932 Data 4 decembrie 2008 20:16:14
Problema Bool Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.14 kb
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

#define T_OPEN 26
#define T_CLOSE 27
#define T_TRUE 28
#define T_FALSE 29
#define T_NOT 30
#define T_AND 31
#define T_OR 32
#define T_END 33

char expr[1010];
bool values[26];
char changes[110];
int tokens[1010];
int postfix[1010];
int numTokens;
int numPostfix;
int numChanges;

int pos;

void read() {
  FILE* f = fopen("bool.in", "rt");
  fgets(expr, 1010, f);
  fscanf(f, "%d\n", &numChanges);
  fgets(changes, numChanges + 1, f);
  fclose(f);
}

int getToken() {
  while (isspace(expr[pos])) {
    pos++;
  }
  if (!expr[pos]) {
    return T_END;
  }
  if (expr[pos] == '(') {
    pos++;
    return T_OPEN;
  }
  if (expr[pos] == ')') {
    pos++;
    return T_CLOSE;
  }

  int pos0 = pos;
  while (isupper(expr[pos])) {
    pos++;
  }
  int len = pos - pos0;
  if (len == 1) {
    return expr[pos0] - 'A';
  }
  if (!strncmp("TRUE", expr + pos0, len)) {
    return T_TRUE;
  } else if (!strncmp("FALSE", expr + pos0, len)) {
    return T_FALSE;
  } else if (!strncmp("NOT", expr + pos0, len)) {
    return T_NOT;
  } else if (!strncmp("AND", expr + pos0, len)) {
    return T_AND;
  } else if (!strncmp("OR", expr + pos0, len)) {
    return T_OR;
  }
  assert(false);
}

void tokenize() {
  int t;
  numTokens = 0;
  do {
    t = getToken();
    tokens[numTokens++] = t;
  } while (t != T_END);
}

int getPriority(int token) {
  switch (token) {
  case T_NOT:
    return 3;
  case T_AND:
    return 2;
  case T_OR:
    return 1;
  }
  return 0;
}

void convertToPostfix() {
  int numParent = 0;
  int tStack[1010], pStack[1010];
  int sp = 0;
  int p;
  numPostfix = 0;
  for (int i = 0; i < numTokens; i++) {
    int t = tokens[i];
    switch (t) {
    case T_OPEN:
      numParent++;
      break;

    case T_CLOSE:
      numParent--;
      break;

    case T_NOT:
    case T_AND:
    case T_OR:
    case T_END:
      p = getPriority(t) + numParent * 10;
      while (sp && pStack[sp - 1] > p) {
        postfix[numPostfix++] = tStack[sp - 1];
        sp--;
      }
      tStack[sp] = t;
      pStack[sp] = p;
      sp++;
      break;

    default:
      postfix[numPostfix++] = t;
    }
  }
}

bool eval() {
  int stack[1010];
  int sp = 0;
  for (int i = 0; i < numPostfix; i++) {
    switch (postfix[i]) {
    case T_NOT:
      stack[sp - 1] = !stack[sp - 1];
      break;
    case T_AND:
      sp--;
      stack[sp - 1] &= stack[sp];
      break;
    case T_OR:
      sp--;
      stack[sp - 1] |= stack[sp];
      break;
    case T_TRUE:
      stack[sp++] = 1;
      break;
    case T_FALSE:
      stack[sp++] = 0;
      break;
    default:
      stack[sp++] = values[postfix[i]];
    }
  }
  return stack[0];
}

void process() {
  memset(values, false, sizeof(values));
  FILE* f = fopen("bool.out", "wt");
  for (int i = 0; i < numChanges; i++) {
    int ord = changes[i] - 'A';
    values[ord] = !values[ord];
    fprintf(f, "%d", eval());
  }
  fclose(f);
}

int main() {
  read();
  tokenize();
  convertToPostfix();
  process();
  return 0;
}