Cod sursa(job #206898)

Utilizator mgntMarius B mgnt Data 10 septembrie 2008 19:16:30
Problema Bool Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.24 kb
# include <iostream>
# include <fstream>
# include <cassert>
using namespace std ;

class Problem {
public  :
  void solve ( ) ;
private :
  void read ( ) ;
  void tokenize ( ) ;
  bool isLetter ( int c ) ;
  void initializeVariables ( ) ;
  bool evaluateExpression ( int & rpos ) ;
  bool evaluateTerm ( int & rpos ) ;
  void write ( ) ;
  #ifdef BE_VERBOSE
  void printText ( int * text ) ;
  #define PRINT_TEXT(s) printText(s)
  void printTokens ( int * token ) ;
  #define PRINT_TOKENS(t) printTokens(t)
  #else
  #define PRINT_TEXT(s)
  #define PRINT_TOKENS(s)
  #endif

  enum ELimits {
      MAXT = 1000
    , MAXN = 100
  } ;
  enum ETokens {
      TNOT = 'Z' - 'A' + 1
    , TAND
    , TOR
    , TTRUE
    , TFALSE
    , TLEFT
    , TRIGHT
    , TEND
  } ;
  int text_ [ MAXT + 10 ] ;
  int flip_ [ MAXN + 10 ] ;
  int token_ [ MAXT + 10 ] ;
  bool value_ [ 'Z' - 'A' + 1 ] ;
  bool eval_ [ MAXN + 10 ] ;
} ;

void Problem :: solve ( ) {
  read ( ) ;
  PRINT_TEXT(text_);
  PRINT_TEXT(flip_);
  tokenize ( ) ;
  PRINT_TOKENS ( token_ ) ;
  initializeVariables ( ) ;
  int pos = 0 , var , tmp ;
  while ( '\n' != (var = flip_ [pos]) ) {
    var -= 'A' ;
    value_ [var] = (! value_ [var] );
    tmp = 0 ;
    eval_ [ pos ] = evaluateExpression ( tmp )  ;
    ++ pos ;
  }
  write ( ) ;
}

void Problem :: read ( ) {
  ifstream is ( "bool.in" ) ;
  int y , i = 0 ;
  do {
    y = is . get () ;
    text_[i] = y ;
    ++ i ;
  } while ( '\n' != y ) ;
  text_[i] = '\n' ;
  do {
    y = is . get () ;
  } while ( '\n' != y ) ;
  i = 0 ;
  while (true) {
    y = 0 ;
    y = is . get () ;
    if ( ('A' <= y) && ('Z' >= i) ) {
      flip_ [i] = y ;
      ++ i ;
      continue ;
    }
    break ;
  }
  flip_ [i] = '\n' ;
}

void Problem :: tokenize ( ) {
  int tk [256] ;
  int ln [256] ;
  #define I(x) static_cast<int>(x)
  tk [I('N')] = TNOT ;
  tk [I('A')] = TAND ;
  tk [I('O')] = TOR ;
  tk [I('T')] = TTRUE  ;
  tk [I('F')] = TFALSE ;
  tk [I('(')] = TLEFT ;
  tk [I(')')] = TRIGHT ;
  ln [I('N')] = 3 ;
  ln [I('A')] = 3 ;
  ln [I('O')] = 2 ;
  ln [I('T')] = 4 ;
  ln [I('F')] = 5 ;
  ln [I('(')] = 1 ;
  ln [I(')')] = 1 ;
  int ind = 0 , pos = 0 , a, b ;
  while ( '\n' != (a = text_[pos]) ) {
    if ( ' ' != a ) {
      b = text_[1+pos];
      if ( isLetter(a) && ! isLetter (b) ) {
        token_ [ind] = a - 'A' ;
        pos += 1 ;
      } else {
        token_ [ind] = tk [a] ;
        pos += ln[a] ;
      }
      ++ ind ;
    } else {
      pos += 1 ;
    }
  }
  token_ [ind]   = TEND ;
  token_ [ind+1] = TEND ;
}

bool Problem :: isLetter ( int c ) {
  return (('A' <= c ) && ('Z' >= c)) ;
}

void Problem :: initializeVariables ( ) {
  int i , n ;
  n = 'Z' - 'A' ;
  for ( i = 0 ; n >= i ; ++ i ) {
    value_ [i] = false ;
  }
}

bool Problem :: evaluateExpression ( int & rpos ) {
  int pos = rpos ;
  int  opA, opB ;
  bool  a , b, c;
  a = evaluateTerm ( pos ) ;
  opA = token_ [pos] ;
  if ( (TEND == opA) || (TRIGHT == opA) ) {
    rpos = pos ;
    return a   ;
  }
  assert ((TAND == opA) || (TOR == opA));
  ++ pos ;
  b = evaluateTerm ( pos ) ;
  opB = token_ [pos] ;
  while (  (TRIGHT != opB) &&  (TEND != opB)  ) {
    assert ((TAND == opB) || (TOR == opB));
    ++ pos ;
    c = evaluateTerm ( pos ) ;
    if ( TAND == opB ) {
      b = (b && c) ;
    } else {
      assert (TOR == opB) ;
      if ( TOR == opA ) {
        a = ( a || b ) ;
      } else {
        assert (TAND == opA) ;
        a = ( a && b ) ;
      }
      b = c ;
      opA = opB ;
    }
    opB = token_ [pos ] ;
  }
  if ( TAND == opA ) {
    a = ( a && b ) ;
  } else {
    assert (TOR == opA ) ;
    a = ( a || b ) ;
  }
  rpos = pos ;
  return a ;
}

bool Problem :: evaluateTerm ( int & rpos ) {
  int pos = rpos ;
  bool bneg = false ;
  while ( TNOT == token_ [pos] ) {
    bneg = ( ! bneg ) ;
    ++ pos ;
  }
  bool bvalue ;
  if (TLEFT == token_ [pos] ) {
    ++ pos ;
    bvalue = evaluateExpression ( pos ) ;
  } else {
    int nvar = token_ [pos] ;
    if ((0<=nvar) && ('Z'-'A'>=nvar)) {
      bvalue = value_ [nvar] ;
    } else {
      assert ((TTRUE == nvar) || (TFALSE == nvar)) ;
      bvalue = (TTRUE == nvar) ;
    }
  }
  rpos = 1 + pos ;
  return bneg ? (! bvalue ) : bvalue ;
}

void Problem :: write ( ) {
  ofstream os ( "bool.out" ) ;
  int pos = 0 ;
  while ( '\n' != flip_ [pos] ) {
    os << (eval_ [pos] ? 1 : 0 ) ;
    ++ pos ;
  }
  os << endl ;
}

int main ( ) {
  Problem o ;
  o . solve ( ) ;
  return 0 ;
}

#ifdef BE_VERBOSE
void Problem :: printText ( int * text ) {
  while ('\n' != (*text) ) {
    cout << static_cast < char > ( *text ) ;
    ++ text ;
  }
  cout << '\n' ;
}
void Problem :: printTokens ( int * token ) {
  char const * textForToken [] = { "NOT", "AND", "OR", "TRUE", "FALSE", "(", ")" } ;
  int t ;
  while (TEND != (t = (* token))) {
    ++ token ;
    if ((0 <= t) && (('Z'-'A')>= t)) {
      cout << static_cast < char > ('A' + t ) ;
    } else if (TEND > t) {
      t -= ( 'Z' - 'A' + 1 ) ;
      cout << textForToken [t] ;
    } else {
      cout << "invalid value in token array\n" ;
    }
    cout << ' ' ;
  }
  cout << endl ;
}
#endif