Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- size_t mallocCount = 0;
- size_t callocCount = 0;
- size_t reallocCount = 0;
- size_t freeCount = 0;
- void* my_malloc(size_t _size) {
- mallocCount++;
- return malloc(_size);
- }
- void* my_calloc(size_t _num, size_t _size) {
- callocCount++;
- return calloc(_num, _size);
- }
- void* my_realloc(void* _memory, size_t _size) {
- if (_memory == NULL) return my_malloc(_size);
- reallocCount++;
- return realloc(_memory, _size);
- }
- void my_free(void* _memory) {
- freeCount++;
- free(_memory);
- }
- struct TreeStruct {
- int res;
- char op;
- char var;
- struct TreeStruct* left;
- struct TreeStruct* right;
- };
- typedef struct TreeStruct Tree;
- void free_tree(Tree* tree) {
- if (tree->left != NULL) free_tree(tree->left);
- if (tree->right != NULL) free_tree(tree->right);
- my_free(tree);
- }
- Tree* copy_tree(Tree* tree) {
- Tree* n = my_malloc(sizeof(Tree));
- n->res = tree->res;
- n->op = tree->op;
- n->var = tree->var;
- n->left = NULL;
- n->right = NULL;
- if (tree->left != NULL) n->left = copy_tree(tree->left);
- if (tree->right != NULL) n->right = copy_tree(tree->right);
- return n;
- }
- const int orderLength = 7;
- const char order[] = {'#', '^', '*', '/', '%', '+', '-', '\0'};
- const char openBracket = '(';
- const char closeBracket = ')';
- const char parseCommandStr[] = "parse\0";
- const char loadPrfCommandStr[] = "load_prf\0";
- const char loadPstCommandStr[] = "load_pst\0";
- const char savePrfCommandStr[] = "save_prf\0";
- const char savePstCommandStr[] = "save_pst\0";
- const char evalCommandStr[] = "eval\0";
- size_t __intLength(int a) {
- int r = a / 10;
- if (r == 0) return 1;
- return __intLength(r) + 1;
- }
- size_t intLength(int a) {
- return __intLength(a) + (a < 0);
- }
- int __findCharExclude(const char* str, const char toFind, int left, int right, int last) {
- size_t lenStr = strlen(str);
- int res = -1;
- for (int i = 0; i < lenStr; i++) {
- if (i >= left && i <= right) continue;
- if (str[i] == toFind) {
- if (!last) return i;
- res = i;
- }
- }
- return res;
- }
- int findCharExclude(const char* str, const char toFind, int left, int right) {
- return __findCharExclude(str, toFind, left, right, 0);
- }
- int findChar(const char* str, const char toFind) {
- return findCharExclude(str, toFind, -1, -1);
- }
- int countChar(const char* str, const char toFind) {
- size_t lenStr = strlen(str);
- int counter = 0;
- for (int i = 0; i < lenStr; i++) {
- if (str[i] == toFind) {
- counter++;
- }
- }
- return counter;
- }
- char* substr(const char* str, size_t from, size_t to) {
- if (from > to) return my_malloc(0);
- size_t newStrLen = to - from + 1;
- char* newStr = my_calloc(newStrLen, sizeof(char));
- newStr[newStrLen-1] = '\0';
- for (size_t i = from; i < to; i++) {
- newStr[i-from] = str[i];
- }
- return newStr;
- }
- char* removeAllChar(const char* str, const char toRemove) {
- int toRemoveCharsCount = countChar(str, toRemove);
- size_t strLen = strlen(str);
- char* out = my_calloc(strLen - toRemoveCharsCount + 1, sizeof(char));
- out[toRemoveCharsCount] = '\0';
- int outC = 0;
- for (size_t i = 0; i < strLen; i++) {
- if (str[i] == toRemove) continue;
- out[outC++] = str[i];
- }
- return out;
- }
- void fillStr(char** str, size_t count, char what) {
- for (size_t i = 0; i < count; i++) {
- (*str)[i] = what;
- }
- }
- int isDigit(const char c) {
- return '0' <= c && c <= '9';
- }
- int isOperator(const char c) {
- return findChar(order, c) != -1;
- }
- int isVariable(const char c) {
- return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
- }
- int isBrackets(const char c) {
- return c == openBracket || c == closeBracket;
- }
- int isGoodExpr(const char* str) {
- size_t strLen = strlen(str);
- for (size_t i = 0; i < strLen; i++) {
- // if not
- if (!(
- isDigit(str[i]) ||
- isOperator(str[i]) ||
- isVariable(str[i]) ||
- isBrackets(str[i])
- )) return 0;
- }
- return 1;
- }
- int isGoodExprPrfPst(const char* str) {
- size_t strLen = strlen(str);
- for (size_t i = 0; i < strLen; i++) {
- // if not
- if (!(
- isDigit(str[i]) ||
- isOperator(str[i]) ||
- isVariable(str[i]) ||
- str[i] == ' '
- )) return 0;
- }
- return 1;
- }
- int isInt(const char* str, int right) {
- int strLen = (int)strlen(str);
- if (right < strLen) strLen = right;
- for (int i = 0; i < strLen; i++) {
- if (!isDigit(str[i])) return 0;
- }
- return 1;
- }
- int strToInt(const char* str) {
- char* eptr;
- return strtol(str, &eptr, 10);
- }
- int gcd(int a, int b) {
- if (a == 0) return b;
- if (b == 0) return a;
- if (a > b) return gcd(a - b, b);
- else return gcd(a, b - a);
- }
- int my_pow(int a, int b) {
- if (b-- == 0) return 1;
- for (size_t i = 0; i < b; i++) {
- a *= a;
- }
- return a;
- }
- // calculates tree - expression like: tree->left->res tree->operator tree->right->res
- // returns 1 if good else 0
- int calc(Tree* tree) {
- if (tree->left == NULL || tree->right == NULL) return 0;
- if (tree->left->var != '\0' || tree->right->var != '\0') {
- tree->res = 1;
- tree->var = '.';
- return 1;
- }
- if (tree->op == '#') {
- if (tree->left->res < 0 || tree->right->res < 0) return 0;
- tree->res = gcd(tree->left->res, tree->right->res);
- }
- else if (tree->op == '^') {
- if (tree->right->res < 0) return 0;
- tree->res = my_pow(tree->left->res, tree->right->res);
- }
- else if (tree->op == '*') {
- tree->res = tree->left->res * tree->right->res;
- }
- else if (tree->op == '/') {
- if (tree->right->res == 0) return 0;
- tree->res = tree->left->res / tree->right->res;
- }
- else if (tree->op == '%') {
- tree->res = tree->left->res % tree->right->res;
- }
- else if (tree->op == '+') {
- tree->res = tree->left->res + tree->right->res;
- }
- else if (tree->op == '-') {
- tree->res = tree->left->res - tree->right->res;
- }
- return 1;
- }
- int isThereUnnecessaryBrackets(const char* str, int right) {
- if (right < 3) return 0;
- return str[0] == openBracket && str[right-1] == closeBracket;
- }
- char* removeUnnecessaryBrackets(const char* str, int right) {
- if (right > 2 && str[0] == openBracket && str[right - 1] == closeBracket) {
- return substr(str, 1, right - 1);
- }
- char* res = my_calloc(right+1, sizeof(char));
- strcpy(res, str);
- res[right] = '\0';
- return res;
- }
- int findLastOrderedOperator(const char* expr, int* res, int right) {
- int exprLen = (int)strlen(expr);
- if (right < exprLen) exprLen = right;
- int bracketIsNotClosed = 0;
- *res = -1;
- int orderRes = orderLength;
- int currentOrder;
- for (int i = 0; i < exprLen; i++) {
- if (expr[i] == openBracket) {
- bracketIsNotClosed++;
- continue;
- }
- if (expr[i] == closeBracket) {
- bracketIsNotClosed--;
- continue;
- }
- if (bracketIsNotClosed > 0) continue;
- if (isOperator(expr[i])) {
- currentOrder = orderLength - findChar(order, expr[i]) - 1;
- if (currentOrder < orderRes) {
- orderRes = currentOrder;
- *res = i;
- }
- }
- }
- if (*res == -1) return -1;
- return *res;
- }
- int __parse(char* expr, Tree* tree, int leftBorder, int rightBorder) {
- //TODO: some error checks
- int lastOperatorPos;
- int res = findLastOrderedOperator(&expr[leftBorder], &lastOperatorPos, rightBorder - leftBorder);
- if (!res) return 0;
- tree->var = '\0';
- if (lastOperatorPos != -1) {
- char op = expr[leftBorder + lastOperatorPos];
- Tree* left = my_malloc(sizeof(Tree));
- int noError = __parse(expr, left, leftBorder, leftBorder + lastOperatorPos);
- if (!noError) return 0;
- Tree* right = my_malloc(sizeof(Tree));
- noError = __parse(expr, right, leftBorder + lastOperatorPos + 1, rightBorder);
- if (!noError) return 0;
- tree->left = left;
- tree->right = right;
- tree->op = op;
- noError = calc(tree);
- if (!noError) return 0;
- }
- else {
- if (isInt(&expr[leftBorder], rightBorder - leftBorder) || isVariable(expr[leftBorder])) {
- tree->left = NULL;
- tree->right = NULL;
- tree->res = 1;
- tree->op = '\0';
- if (isVariable(expr[leftBorder])) {
- tree->var = expr[leftBorder];
- }
- else {
- tree->res = strToInt(&expr[leftBorder]);
- }
- }
- else if (isThereUnnecessaryBrackets(&expr[leftBorder], rightBorder - leftBorder)) {
- char* goodExpr = removeUnnecessaryBrackets(&expr[leftBorder], rightBorder - leftBorder);
- res = __parse(goodExpr, tree, 0, strlen(goodExpr));
- my_free(goodExpr);
- if (!res) return 0;
- }
- else {
- return 0;
- }
- }
- return 1;
- }
- int parse(char* expr, Tree* tree) {
- char* exprWithoutSpaces = removeAllChar(expr, ' ');
- if (
- !isGoodExpr(exprWithoutSpaces) ||
- !__parse(exprWithoutSpaces, tree, 0, strlen(exprWithoutSpaces))
- ) {
- my_free(exprWithoutSpaces);
- return 0;
- }
- my_free(exprWithoutSpaces);
- return 1;
- }
- size_t __prfOrPstLength(Tree* tree) {
- size_t len = (tree->op != '\0')*2;
- if (tree->left != NULL) {
- len += __prfOrPstLength(tree->left);
- len += __prfOrPstLength(tree->right);
- }
- else {
- len += 1 + intLength(tree->res);
- }
- return len;
- }
- size_t prfOrPstLength(Tree* tree) {
- return __prfOrPstLength(tree) - 1;
- }
- int __savePrfOrPst(Tree* tree, char* out, int pst) {
- int pos = 0;
- if (tree->op != '\0') {
- if (!pst) {
- out[0] = tree->op;
- pos += 2;
- }
- pos += __savePrfOrPst(tree->left, &out[pos], pst);
- pos += __savePrfOrPst(tree->right, &out[pos], pst);
- if (pst) {
- out[pos] = tree->op;
- pos += 2;
- }
- }
- else {
- if (tree->var == '\0') {
- itoa(tree->res, out, 10);
- pos += (int)intLength(tree->res) + 1;
- out[pos - 1] = ' ';
- }
- else {
- out[0] = tree->var;
- pos += 2;
- }
- }
- return pos;
- }
- char* savePrf(Tree* tree) {
- size_t prfLen = prfOrPstLength(tree);
- char* prf = my_calloc(prfLen + 1, sizeof(char));
- fillStr(&prf, prfLen, ' ');
- __savePrfOrPst(tree, prf, 0);
- prf[prfLen] = '\0';
- return prf;
- }
- char* savePst(Tree* tree) {
- size_t prfLen = prfOrPstLength(tree);
- char* pst = my_calloc(prfLen + 1, sizeof(char));
- fillStr(&pst, prfLen, ' ');
- __savePrfOrPst(tree, pst, 1);
- pst[prfLen] = '\0';
- return pst;
- }
- int __loadPrf(const char* expr, Tree* tree, int* pos) {
- int noErr;
- tree->op = '\0';
- tree->var = '\0';
- tree->res = 1;
- if (!isOperator(expr[*pos])) {
- tree->left = NULL;
- tree->right = NULL;
- tree->op = '\0';
- if (isVariable(expr[*pos])) {
- tree->var = expr[*pos];
- *pos += 2;
- }
- else {
- tree->res = strToInt(&expr[*pos]);
- *pos += (int)intLength(tree->res) + 1;
- }
- return 1;
- }
- tree->op = expr[*pos];
- *pos += 2;
- tree->left = my_malloc(sizeof(Tree));
- tree->right = my_malloc(sizeof(Tree));
- int lPos = 0;
- noErr = __loadPrf(&expr[*pos], tree->left, &lPos);
- if (!noErr) return 0;
- *pos += lPos;
- lPos = 0;
- noErr = __loadPrf(&expr[*pos], tree->right, &lPos);
- if (!noErr) return 0;
- *pos += lPos;
- noErr = calc(tree);
- if (!noErr) return 0;
- return 1;
- }
- int loadPrf(const char* expr, Tree* tree) {
- if (!isGoodExprPrfPst(expr)) return 0;
- //TODO: check
- int pos = 0;
- int noErr = __loadPrf(expr, tree, &pos);
- return noErr && pos - 1 == strlen(expr);
- }
- int __loadPst(const char* expr, Tree* tree, int* pos) {
- int noErr;
- tree->op = '\0';
- tree->var = '\0';
- tree->res = 1;
- if (!isOperator(expr[*pos])) {
- tree->left = NULL;
- tree->right = NULL;
- tree->op = '\0';
- for (; *pos != 0 && expr[*pos] != ' '; (*pos)--) ;
- if (*pos != 0) (*pos)++;
- if (isVariable(expr[*pos])) {
- tree->var = expr[*pos];
- }
- else {
- tree->res = strToInt(&expr[*pos]);
- }
- *pos -= 2;
- return 1;
- }
- tree->op = expr[*pos];
- *pos -= 2;
- tree->left = my_malloc(sizeof(Tree));
- tree->right = my_malloc(sizeof(Tree));
- noErr = __loadPst(&expr[0], tree->right, pos);
- if (!noErr) return 0;
- noErr = __loadPst(&expr[0], tree->left, pos);
- if (!noErr) return 0;
- noErr = calc(tree);
- if (!noErr) return 0;
- return 1;
- }
- int loadPst(const char* expr, Tree* tree) {
- if (!isGoodExprPrfPst(expr)) return 0;
- //TODO: check
- int pos = (int)strlen(expr) - 1;
- int noErr = __loadPst(expr, tree, &pos);
- return noErr && pos == -2;
- }
- // returns 2 if error, 1 if modified, 0 if not modified
- int __eval(const char var, const int val, Tree* tree) {
- if (tree->var == var) {
- tree->res = val;
- tree->var = '\0';
- return 1;
- }
- if (tree->left != NULL) {
- int modified = __eval(var, val, tree->left) | __eval(var, val, tree->right);
- // passthrough error
- if (modified & 0x2) return 2;
- // if modified
- if (modified & 0x1) {
- tree->var = '\0';
- int noError = calc(tree);
- if (!noError) return 2;
- return 1;
- }
- }
- return 0;
- }
- int eval(char* expr, Tree* tree) {
- int exprLen = (int) strlen(expr);
- int pos;
- char var;
- int val;
- int eRes;
- while (exprLen > 2) {
- if (expr[1] != '=') return 0;
- var = expr[0];
- val = strToInt(&expr[2]);
- eRes = __eval(var, val, tree);
- // catch error
- if (eRes & 0x2) return 0;
- pos = 2;
- for (; expr[pos] != ','; pos++) {
- if (pos + 1 == exprLen) return tree->var == '\0';
- }
- expr = &expr[pos+1];
- exprLen = (int) strlen(expr);
- }
- return tree->var == '\0';
- }
- int commandToExpression(char** str) {
- int fullCommandLen = (int)strlen(*str);
- int spacePos = findChar(*str, ' ');
- if (spacePos == -1) return 0;
- for (; spacePos + 1 != fullCommandLen && (*str)[spacePos] == ' '; spacePos++) ;
- if (spacePos + 1 == fullCommandLen) return 0;
- *str = &((*str)[spacePos]);
- return 1;
- }
- void writeFile(char* data) {
- FILE* f = fopen("output.txt", "a");
- fprintf(f, "%s\n", data);
- fclose(f);
- }
- void writeFileInt(int data) {
- FILE* f = fopen("output.txt", "a");
- fprintf(f, "%i\n", data);
- fclose(f);
- }
- int doCommand(char* str, Tree** tree, int print) {
- // in the start it's command
- if (strstr(str, parseCommandStr)) {
- // now it's expression
- if (!commandToExpression(&str)) return 0;
- Tree* ntree = my_malloc(sizeof(Tree));
- ntree->left = NULL;
- ntree->right = NULL;
- if (parse(str, ntree)) {
- if (*tree != NULL) free_tree(*tree);
- *tree = ntree;
- if (print) {
- printf("success\n");
- }
- else {
- writeFile("success");
- }
- }
- else {
- free_tree(ntree);
- if (print) {
- printf("incorrect\n");
- }
- else {
- writeFile("incorrect");
- }
- }
- return 1;
- }
- else if (strstr(str, loadPrfCommandStr)) {
- // now it's expression
- if (!commandToExpression(&str)) return 0;
- Tree* ntree = my_malloc(sizeof(Tree));
- ntree->left = NULL;
- ntree->right = NULL;
- if (loadPrf(str, ntree)) {
- if (*tree != NULL) free_tree(*tree);
- *tree = ntree;
- if (print) {
- printf("success\n");
- }
- else {
- writeFile("success");
- }
- }
- else {
- free_tree(ntree);
- if (print) {
- printf("incorrect\n");
- }
- else {
- writeFile("incorrect");
- }
- }
- return 1;
- }
- else if (strstr(str, loadPstCommandStr)) {
- // now it's expression
- if (!commandToExpression(&str)) return 0;
- Tree* ntree = my_malloc(sizeof(Tree));
- ntree->left = NULL;
- ntree->right = NULL;
- if (loadPst(str, ntree)) {
- if (*tree != NULL) free_tree(*tree);
- *tree = ntree;
- if (print) {
- printf("success\n");
- }
- else {
- writeFile("success");
- }
- }
- else {
- free_tree(ntree);
- if (print) {
- printf("incorrect\n");
- }
- else {
- writeFile("incorrect");
- }
- }
- return 1;
- }
- else if (strstr(str, savePrfCommandStr)) {
- char* out = savePrf(*tree);
- if (print) {
- printf("%s\n", out);
- }
- else {
- writeFile(out);
- }
- my_free(out);
- return 1;
- }
- else if (strstr(str, savePstCommandStr)) {
- char* out = savePst(*tree);
- if (print) {
- printf("%s\n", out);
- }
- else {
- writeFile(out);
- }
- my_free(out);
- return 1;
- }
- else if (strstr(str, evalCommandStr)) {
- // now it's expression
- if (!commandToExpression(&str)) return 0;
- Tree* toEval = copy_tree(*tree);
- int res = eval(str, toEval);
- if (!res) return 0;
- if (print) {
- printf("%i\n", res);
- }
- else {
- writeFileInt(res);
- }
- free_tree(toEval);
- return 1;
- }
- return 0;
- }
- void writeMemstat() {
- FILE* f = fopen("memstat.txt", "w");
- fprintf(f, "malloc:%zu\n", mallocCount);
- fprintf(f, "realloc:%zu\n", reallocCount);
- fprintf(f, "calloc:%zu\n", callocCount);
- fprintf(f, "free:%zu\n", freeCount);
- fclose(f);
- }
- void fileWork() {
- FILE* f = fopen("input.txt", "r");
- if (!f) return;
- FILE* fo = fopen("output.txt", "w");
- if (!fo) return;
- fclose(fo);
- fseek(f, 0L, SEEK_END);
- int fileLen = ftell(f);
- rewind(f);
- char* command = my_calloc(fileLen + 1, sizeof(char));
- Tree* tree = NULL;
- while (fgets(&command[0], fileLen + 1, f) != NULL) {
- if (command[strlen(command) - 1] == '\n') {
- command[strlen(command) - 1] = '\0';
- if (!doCommand(command, &tree, 0)) {
- //TODO: error?
- writeFile("incorrect");
- continue;
- }
- }
- }
- my_free(command);
- if (tree != NULL) free_tree(tree);
- fclose(f);
- }
- int main() {
- fileWork();
- Tree* tree = NULL;
- // 5*(14-4*2)/2 = 15
- // ( 22 - ( 1 + 1 ) ) / ( 5 * ( 6 - ( 2 + 2 ) ) ) = 2
- // ( ( ( 1 ) ) ) = 1
- // 2 / 2 + 3 * 4 - 6 = 7
- // ( ( ( ( ( ( ( 5 ) ) ) ) ) ) ) = 5
- // 2 * ( 2 * ( 2 * ( 2 * 1 ) ) ) = 16
- // 3 * ( 4 + 7 ) - 6 = 27
- // ( 1 + 2 * ( 1 - 2 ) ) = -1
- // ( 1 + 2 * ( 1 - 2 ) ) * ( 1 + 2 * ( 1 - 2 ) ) = 1
- // 1 * 2 * 3 * 4 * 5 + 20 / 5 = 124
- // 1 * 2 * 3 * 4 * (5 + 20) / 5 = 120
- char* buff = my_calloc(1000, sizeof(char));
- printf("Print nothing to out\n");
- while (gets(buff) != NULL) {
- if (buff[0] == '\0') break;
- if (!doCommand(buff, &tree, 1)) {
- //TODO: error?
- printf("incorrect\n");
- }
- }
- my_free(buff);
- if (tree != NULL) free_tree(tree);
- writeMemstat();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment