Cod sursa(job #2149787)

Utilizator alexge50alexX AleX alexge50 Data 2 martie 2018 23:15:40
Problema Bool Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.84 kb
#include <stdio.h>
#include <stdlib.h>

#include <vector>
#include <string>
#include <cstring>

const int MAX_MEM = 1000;

       std::string AND = std::string("AND"),
                   OR = std::string("OR"),
                   NOT = std::string("NOT"),
                   SPACE = std::string(" "),
                   TRUE = std::string("TRUE"),
                   FALSE = std::string("FALSE"),
                   OPEN_PARENTHESES = std::string("("),
                   CLOSE_PARENTHESES = std::string(")");

class file
{
public:
    file(FILE *fin)
    {
        m_fin = fin;
        m_currentWord = SPACE;
        m_currentChar = fgetc(fin);
    }
    void skipwhite()
    {
        while(m_currentWord == SPACE)
            next();
    }
    void next()
    {
        char *c = &m_currentChar;
        char buffer[1024];

        if(*c == ' ' || *c == '(' || *c == ')' || *c == '\n')
        {
            buffer[0] = *c;
            buffer[1] = 0;
            *c = fgetc(m_fin);
        }
        else
        {
            char *pBuffer = buffer;
            while(isalpha(*c))
                *pBuffer = *c, pBuffer ++, *c = fgetc(m_fin);
            *pBuffer = 0;
        }

        m_currentWord = std::string(buffer);

        //printf("in next(), buffer = '%s'\n", buffer);
    }

    void unget()
    {
        ungetc(m_currentChar, m_fin);
    }

    std::string currentWord()
    {
        return m_currentWord;
    }
private:
    FILE *m_fin;
    std::string m_currentWord;
    char m_currentChar;
};


struct ValueTable
{
    char m_value[128];
};

class Block
{
public:
    virtual int eval(ValueTable *pValueTable) = 0;
};

class Expr
{
public:
    virtual int eval(ValueTable *pValueTable) = 0;

    void AddBlock(Block *pBlock)
    {
        m_blocks.push_back(pBlock);
    }
protected:
    std::vector<Block*> m_blocks;
};

class OrExpr: public Expr
{
public:
    virtual int eval(ValueTable *pValueTable)
    {
        int result = 0;
        for(auto i: m_blocks)
            result = result || i->eval(pValueTable);
        return result;
    }
};

class AndExpr: public Expr
{
public:
    virtual int eval(ValueTable *pValueTable)
    {
        int result = 1;
        for(auto i: m_blocks)
            result = result && i->eval(pValueTable);
        return result;
    }
};

class Variable: public Block
{
public:
    Variable(char ref)
    {
        m_ref = ref;
    }

    virtual int eval(ValueTable *pValueTable)
    {
        return pValueTable->m_value[m_ref];
    }

private:
    char m_ref;
};

class Value: public Block
{
public:
    Value(int value)
    {
        m_value = value;
    }

    virtual int eval(ValueTable *pValueTable)
    {
        return m_value;
    }

private:
    int m_value;
};

class Not
{
public:
    virtual int eval(ValueTable *pValueTable)
    {
        return !m_pBlock->eval(pValueTable);
    }

    void SetPBlock(Block* pBlock){m_pBlock = pBlock;}

private:
    Block* m_pBlock;
};


class MemTable
{
public:
    MemTable(int size = MAX_MEM)
    {
        m_size = size;

        m_memAndExpr = (AndExpr*)malloc(m_size * sizeof(AndExpr));
        m_pLastAndExpr = m_memAndExpr + m_size;

        m_memOrExpr = (OrExpr*)malloc(m_size * sizeof(OrExpr));
        m_pLastOrExpr = m_memOrExpr + m_size;

        m_memVariable = (Variable*)malloc(m_size * sizeof(Variable));
        m_pLastVariable = m_memVariable + m_size;

        m_memValue = (Value*)malloc(m_size * sizeof(Value));
        m_pLastValue = m_memValue + m_size;

        m_memNot = (Not*)malloc(m_size * sizeof(Not));
        m_pLastNot = m_memNot + m_size;
    }

    AndExpr* new_AndExpr(AndExpr value)
    {
        auto *p = m_memAndExpr;
        memcpy(p, &value, sizeof(value));

        m_memAndExpr++;
        return p;
    }

    OrExpr* new_OrExpr(OrExpr value)
    {
        auto *p = m_memOrExpr;
        memcpy(p, &value, sizeof(value));

        m_memOrExpr++;
        return p;
    }

    Value* new_Value(Value value)
    {
        auto *p = m_memValue;
        memcpy(p, &value, sizeof(value));

        m_memValue++;
        return p;
    }

    Variable* new_Variable(Variable value)
    {
        auto *p = m_memVariable;
        memcpy(p, &value, sizeof(value));

        m_memVariable++;
        return p;
    }

    Not* new_Not(Not value)
    {
        auto *p = m_memNot;
        memcpy(p, &value, sizeof(value));

        m_memNot++;
        return p;
    }

private:
    int m_size;
    AndExpr *m_memAndExpr, *m_pLastAndExpr;
    OrExpr *m_memOrExpr, *m_pLastOrExpr;
    Variable *m_memVariable, *m_pLastVariable;
    Value *m_memValue, *m_pLastValue;
    Not *m_memNot, *m_pLastNot;
};

MemTable g_memTable;

Block* ParseOrExpr(file *f);
Block* ParseAndExpr(file *f);
Block* ParseNot(file *f);

int main()
{
    FILE *fin = fopen("bool.in", "r");
    FILE *fout = fopen("bool.out", "w");
    file f = file(fin);
    ValueTable vtable;

    f.next();

    Block *program = ParseOrExpr(&f);
    f.unget();
    int n;

    fscanf(fin, " %d ", &n);

    for(int i = 0; i < 128; i++) vtable.m_value[i] = 0;

    for(int i = 0; i < n; i++)
    {
        char c;
        fscanf(fin, " %c", &c);

        //printf("%c", c);

        vtable.m_value[c] = !vtable.m_value[c];

        fprintf(fout, "%d", program->eval(&vtable));

    }

    fclose(fin);
    fclose(fout);
    return 0;
}

int OrId = 0;

Block* ParseOrExpr(file *f)
{
    int id = OrId++;
    OrExpr *pOrExpr = g_memTable.new_OrExpr(OrExpr());

    pOrExpr->AddBlock(ParseAndExpr(f));

    while(f->currentWord() == OR)
    {
        f->next();
        f->skipwhite();
        pOrExpr->AddBlock(ParseAndExpr(f));
        f->skipwhite();
    }

    return (Block*)pOrExpr;
}

Block* ParseAndExpr(file *f)
{
    AndExpr *pAndExpr = g_memTable.new_AndExpr(AndExpr());

    f->skipwhite();
    pAndExpr->AddBlock(ParseNot(f));

    while(f->currentWord() == AND)
    {
        f->next();
        f->skipwhite();
        pAndExpr->AddBlock(ParseNot(f));
        f->skipwhite();
    }

    return (Block*)pAndExpr;
}

Block* ParseNot(file *f)
{
    Not *pNot = NULL;
    Block *pSubBlock;

    f->skipwhite();

    if(f->currentWord() == NOT)
    {
        pNot = g_memTable.new_Not(Not());
        f->next();
    }

    f->skipwhite();

    if(f->currentWord() == OPEN_PARENTHESES)
    {
        f->next();
        f->skipwhite();
        pSubBlock = ParseOrExpr(f);
        f->next();
        f->skipwhite();
    }
    else if(f->currentWord() == TRUE)
    {
        pSubBlock = g_memTable.new_Value(Value(true));
        f->next();
        f->skipwhite();
    }
    else if(f->currentWord() == FALSE)
    {
        pSubBlock = g_memTable.new_Value(Value(false));
        f->next();
        f->skipwhite();
    }
    else
    {
        pSubBlock = g_memTable.new_Variable(Variable(*(f->currentWord().begin())));
        f->next();
        f->skipwhite();
    }


    if(pNot != NULL)
    {
        pNot->SetPBlock(pSubBlock);
        return (Block*)pNot;
    }
    else return pSubBlock;
}