#include <iostream>
#include <stdlib.h>
#include <fstream>
using namespace std;
#define TRUE 1
#define FALSE 0
//#define DTEST
int main();
int _tmain(int argc, char* argv[])
{
return main();
}
// BINARY TREE
enum NODETYPE
{
NOT = 1, // operation = NOT
OR, // operation = OR
AND, // operation = AND
VALUE, // VALUE - variable
CT_VALUE // CT_VALUE - variable
};
char * nodetypes[] =
{
"",
"NOT",
"OR",
"AND",
"VALUE",
"CT_VALUE"
};
struct NODE
{
// Constructor
NODE()
: type (VALUE)
, iVal(-1)
, left(NULL)
, right(NULL)
, up(NULL)
{;}
// Members
NODETYPE type; // NODE TYPE
union{
int iVal; // index in vals[] | NODETYPE::VALUE
int value; // value | NODETYPE::CT_VALUE
int prior; // priority | NODETYPE::NOT, AND, OR
};
NODE *left; // left node
NODE *right; // right node
NODE *up; // upper node (parent)
};
// GLOBALS
NODE * root; // binary tree
char expr[1001]; // unparsed expression
char vars[100]; // variable names
char vals[40]; // variable values (A - Z)
int N; // number of variables
#define SETVARVALUE(char_val,value) vals[char_val-'A'] = (value)
#define GETVARVALUE(char_val) (vals[char_val-'A'])
#define ISOPNODE(node) (node->type >= NOT && node->type <= AND)
#define ISVALNODE(node) (node->type == CT_VALUE || node->type == VALUE)
int evaluate_tree(NODE * node);
#ifdef DTEST
void print_spaces(int spaces)
{
if( !spaces )return;
printf("-");
while(spaces-- > 0)
printf(" ");
}
void print_tree(NODE* root,char ctype,int level,int evaluate = 1)
{
print_spaces(level*2);
printf("%c:%s",
ctype,
nodetypes[root->type]);
// values
if( root->type == VALUE )
printf(" %c=%d ",
root->iVal,
GETVARVALUE(root->iVal));
else
// constants
if( root->type == CT_VALUE )
printf(" %s ",
root->value ? "TRUE":"FALSE");
else
// operators
if( ISOPNODE(root) )
printf(" prior:%d",
root->prior );\
else
throw; // unknown node
printf("\tEV: %d",evaluate_tree(root));
printf("\n");
if( root->left ) print_tree(root->left,'L',level+1);
if( root->right) print_tree(root->right,'R',level+1);
}
#endif//DTEST
NODE * select_node( const char * word, int cch )
{
// New binary NODE
NODE* node = new NODE;
if( cch < 0 || cch == 0 ) throw;// safety
// Select type
// OPERATIONS
if( strcmp(word,"AND") == 0 )
{
node->type = AND;
node->prior = 1;
}else
if( strcmp(word,"OR") == 0 )
{
node->type = OR;
node->prior = 0;
}else
if( strcmp(word,"NOT") == 0 )
{
node->type = NOT;
node->prior = 2;
}else
// VALUES
if( strcmp(word,"FALSE") == 0 )
{
node->type = CT_VALUE;
node->value = 0;
}else
if( strcmp(word,"TRUE") == 0 )
{
node->type = CT_VALUE;
node->value = 1;
}else
// VARIABLE
{
// failure
if( cch != 1 )
throw; // variables can only be one char long
node->type = VALUE;
node->iVal = word[0];
}
return node;
}
int evaluate_tree(NODE * node)
{
if( node->type == NOT )
{
NODE * val;
if( node->left != NULL )
{
val = node->left;
if( node->right != NULL )
throw;// NOT has only one operand
}else
if( node->right != NULL )
{
val = node->right;
}else
throw; // no operands defined
return !evaluate_tree(val);
}else
if( node->type == AND )
{
return evaluate_tree(node->left) && evaluate_tree(node->right);
}else
if( node->type == OR )
{
return evaluate_tree(node->left) || evaluate_tree(node->right);
}else
if( ISVALNODE(node) )
{
if( node->left != NULL ||
node->right != NULL )
throw; // value nodes should not have descendants
return GETVARVALUE(node->iVal);
}
throw;
return 0;
}
// Construct Binary TREE
const char *parse_expr(const char * expr,NODE *& root)
{
int iword; // index of current word char
char word[10]; // no words must exceeed 4 chars
const char * seek; // movable ptr to expresion
NODE * node; // current node
NODE * prevnode; // previous node
// Initialize parsing
seek = expr; // init seeker
prevnode = NULL;
while( *seek != '\0' && *seek != ')' )
{
// trim
while( *seek == ' ' ) seek++;
// SUBEXPRESION
if( *seek == '(' )
{
NODE * subroot;
seek = parse_expr(seek+1,subroot);
if( subroot )
if( prevnode == NULL )
// No previous node, mark subexpresion as previous
prevnode = subroot;
else
// Bind to the right of the previous node
{
if( ISVALNODE(prevnode) )
throw; // previous node followed by a subexpression
if( prevnode->right != NULL )
throw; // previous node operation has full slots (safety)
prevnode->right = subroot;
}
// jump to next iteration
continue;
}
// Read word
iword = 0;
while(
*seek != '\0' &&
*seek != ' ' &&
*seek != '(' &&
*seek != ')' &&
iword < int(sizeof(word)) )
word[iword++] = *seek++;
if( iword == 0 )
break; // no more readable words
// failure
if( iword == sizeof(word) )
throw;
// trucate
word[iword] = 0;
// Select node based on word
node = select_node(word,iword);
if( node->type == NOT )
// NOT
{
if( prevnode != NULL )
if( prevnode->left == NULL )
prevnode->left = node,
node->up = prevnode;
else
if( prevnode->right == NULL )
prevnode->right = node,
node->up = prevnode;
else
throw; // slots are full
}else
if( ISOPNODE(node) )
// OPERATION
{
if( prevnode )
{
NODE * seek = prevnode;
// Search for an operand with a HIGHER priority
while(seek->up != NULL)
{
if( ISOPNODE(seek->up) == FALSE )
throw; // upper value node isn't an operator
if( node->prior > seek->up->prior )
{
NODE * save = seek->up->right;
// Inject
seek->up->right = node;
node->up = seek->up;
node->left = save;
save->up = node;
seek = NULL;
break;
}
seek = seek->up;
}
if( seek != NULL )
// add operator on the top of the stack
if( prevnode->up != NULL ) // previous value has a parent
{
node->left = seek;
seek->up = node;
}else
// Operator will be on the top of the stack
{
node->left = prevnode;
prevnode->up = node;
}
}else
if( node->type != NOT )
throw; // no previous operator for NOT
}else
// VALUE
{
if( prevnode )
{
if( ISVALNODE(prevnode) )
throw; // previous node is another value
// Add value to the left (operand should be NOT)
if( prevnode->left == NULL )
prevnode->left = node,
node->up = prevnode;
else
// Add value to the right (to the previous operatop)
if( prevnode->right == NULL )
prevnode->right = node,
node->up = prevnode;
else
throw; // op slots are full
}
}
// Mark previous node
prevnode = node;
}// while(seek)
// trim (safety)
while( *seek == ' ' ) seek ++;
// jump over ')'
if( *seek == ')' ) seek ++;
// walk-up root
root = prevnode;
if( root )
while( root->up != NULL )
root= root->up;
return seek;
}
int main()
{
// Open & Start
ifstream in("bool.in");
ofstream out("bool.out");
// READ
in.get(expr,1001); // expresion
in >> N; // number of vars
int i(0); // variables
while(i++ < N)
in >> vars[i], // read variable name
vars[i] = toupper(vars[i]); // make sure is UPPERCASE
// Zero-out values
for(i = 0;i <= int('Z'-'A'); i++)
vals[i] = 0;
// Parse expression
NODE * root(NULL);
parse_expr(expr,root);
#ifdef DTEST
// Printout Expression
printf("%s\n",expr);
print_tree(root,'T',0);
#endif//DTEST
// Switch vars
for( i = 0 ; i < N ; i ++ )
{
// Switch
SETVARVALUE(vars[i],!GETVARVALUE(vars[i]));
out << ((evaluate_tree(root) != 0)? 1:0);
#ifdef DTEST
printf("Switching: %c (before:%d after:%d)\n",
vars[i],
!GETVARVALUE(vars[i]),
GETVARVALUE(vars[i]));
print_tree(root,'T',0);
#endif//DTEST
}
// Exit & Close
out.close();
in.close();
return 0;
}