Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cmath>
- #include <vector>
- #include <string>
- #include <map>
- #define CALC_STATE_NUMBER 0
- #define CALC_STATE_OPERATION 1
- #define CALC_STATE_BRACKET 2
- #define CALC_STATE_ERROR 3
- #define CALC_STATE_VARIABLE 4
- #define CALC_PRIORITY_LENGTH 5
- #define CALC_PRIORITY_BRACKET 0
- #define CALC_PRIORITY_FUNCTION 1
- #define CALC_PRIORITY_UNARY 2
- #define CALC_PRIORITY_BINARY_0 3
- #define CALC_PRIORITY_BINARY_1 4
- #define CALC_IS_COUNTABLE(x) ((x) == CALC_STATE_NUMBER || (x) == CALC_STATE_BRACKET || (x) == CALC_STATE_VARIABLE)
- /*
- CalculationElement: pair < element type , element value >
- element types:
- 0: number
- 1: operation
- 2: bracket
- element value:
- 1:
- 0: +
- 1: -
- 2: *
- 3: /
- 4: **
- */
- typedef std::pair<unsigned char, long double> CalculationElement;
- inline bool isCharLetter(char c) {
- return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
- }
- CalculationElement parseOperation(const std::string &operation) {
- if (operation == "x") { // Extra
- return CalculationElement(CALC_STATE_VARIABLE, 0);
- }
- static std::map<std::string, long double> operations;
- operations["+"] = 0;
- operations["-"] = 1;
- operations["*"] = 2;
- operations["/"] = 3;
- operations["sin"] = 4;
- operations["cos"] = 5;
- operations["tg"] = 6;
- operations["ctg"] = 7;
- operations["exp"] = 8;
- std::map<std::string, long double>::iterator findIt = operations.find(operation);
- if (findIt != operations.end())
- return CalculationElement(CALC_STATE_OPERATION, findIt->second);
- // Check /[\-]+/ and /[\+]+/
- /*
- unsigned char addOperators = 255;
- for (size_t i = 0; i < operation.size(); i++) {
- if (operation[i] == '+') {
- if (addOperators == 255) {
- addOperators = 0;
- }
- } else if (operation[i] == '-') {
- if (addOperators == 255) {
- addOperators = 1;
- } else {
- addOperators = (unsigned char)1 - addOperators; // 1 -> 0; 0 -> 1
- }
- } else {
- addOperators = 255;
- break;
- }
- }
- if (addOperators != 255)
- return CalculationElement(CALC_STATE_OPERATION, addOperators);
- */
- // Raise error
- return CalculationElement(CALC_STATE_ERROR, 0);
- }
- int parseLine(std::vector<std::vector<CalculationElement> > *elementsVector) {
- char c; // temp char
- unsigned char state = 255;
- int numberPrecision = -1;
- long double number = 0;
- std::string operation = "";
- std::vector<size_t> bracketIds;
- bracketIds.push_back(0);
- while (std::cin.get(c) && c != '\n') {
- if (std::isspace(c)) continue;
- // Parse current char
- if (c >= '0' && c <= '9') {
- // Operation
- if (state == CALC_STATE_OPERATION) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(parseOperation(operation));
- operation = "";
- }
- unsigned char numeral = (unsigned char) c - '0'; // always non-negative
- if (numberPrecision == -1) {
- number = (number * 10 + numeral);
- } else {
- number = number + numeral / powf(10.0, (float) numberPrecision);
- numberPrecision++;
- }
- state = CALC_STATE_NUMBER;
- } else if (c == '.') {
- if (numberPrecision == 1) {
- // Raise error
- }
- numberPrecision = 1;
- } else {
- if (state == CALC_STATE_NUMBER) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(std::make_pair(state, number));
- number = 0;
- numberPrecision = -1;
- }
- switch (c) {
- case '(': {
- if (state == CALC_STATE_OPERATION) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(parseOperation(operation));
- operation = "";
- }
- state = CALC_STATE_BRACKET;
- size_t bracketId = *bracketIds.rbegin(); // Current braket
- size_t newBracketId = elementsVector->size(); // New bracket
- (*elementsVector)[bracketId].push_back(std::make_pair(CALC_STATE_BRACKET, newBracketId));
- bracketIds.push_back(newBracketId);
- std::vector<CalculationElement> tempVector;
- elementsVector->push_back(tempVector);
- break;
- }
- case ')':
- if (state == CALC_STATE_OPERATION) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(parseOperation(operation));
- operation = "";
- }
- state = CALC_STATE_BRACKET;
- bracketIds.pop_back();
- break;
- default:
- if (state != CALC_STATE_OPERATION && c == 'x') {
- // TODO: Add X
- state = CALC_STATE_VARIABLE;
- break;
- }
- if (state == CALC_STATE_OPERATION && (isCharLetter(*operation.rbegin()) != isCharLetter(c) || c == '+' || c == '-')) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(parseOperation(operation));
- operation = "";
- }
- state = CALC_STATE_OPERATION;
- operation += c;
- break;
- }
- }
- }
- // Handling last value
- if (state == CALC_STATE_NUMBER) {
- (*elementsVector)[*bracketIds.rbegin()].push_back(std::make_pair(state, number));
- }
- return 0;
- }
- int calculateElements(std::vector<CalculationElement> *elements,
- std::vector<std::vector<CalculationElement> > *elementsVector) {
- if (elements->size() == 1) {
- unsigned char state = elements->begin()->first;
- if (state == CALC_STATE_NUMBER) {
- return 0;
- } else if (state == CALC_STATE_BRACKET) {
- // pass
- } else {
- // Raise error
- }
- }
- /*
- 0: bracket
- 1: function call
- 2: unary operations
- 3: multiply, divide
- 4: +, -
- */
- // Priority setup
- std::vector<std::vector<CalculationElement>::iterator> priorityQueues[CALC_PRIORITY_LENGTH];
- for (std::vector<CalculationElement>::iterator it = elements->begin(); it != elements->end(); it++) {
- switch (it->first) {
- case CALC_STATE_OPERATION:
- if (it+1 == elements->end()) {
- // Raise error
- }
- if (it == elements->begin()) {
- if (CALC_IS_COUNTABLE((it+1)->first) || ((it+1)->first == CALC_STATE_OPERATION && (it+1)->second >= 4)) { // it is unary operation
- if (it->second >= 4) {
- priorityQueues[CALC_PRIORITY_FUNCTION].push_back(it);
- } else {
- priorityQueues[CALC_PRIORITY_UNARY].push_back(it);
- }
- }
- } else {
- if (!CALC_IS_COUNTABLE((it-1)->first) && CALC_IS_COUNTABLE((it+1)->first)) { // it is unary operation
- if (it->second >= 4) {
- priorityQueues[CALC_PRIORITY_FUNCTION].push_back(it);
- } else {
- priorityQueues[CALC_PRIORITY_UNARY].push_back(it);
- }
- } else if (CALC_IS_COUNTABLE((it-1)->first) && (CALC_IS_COUNTABLE((it+1)->first) || ((it+1)->first == CALC_STATE_OPERATION && (it+1)->second >= 4))) { // binary operation
- if (it->second >= 4) {
- priorityQueues[CALC_PRIORITY_FUNCTION].push_back(it);
- } else if (it->second <= 3 && it->second >= 2) {
- priorityQueues[CALC_PRIORITY_BINARY_0].push_back(it);
- } else {
- priorityQueues[CALC_PRIORITY_BINARY_1].push_back(it);
- }
- } else {
- // Unexpected situation
- std::cout << "Unexpected operators (priority)" << std::endl;
- }
- }
- break;
- case CALC_STATE_NUMBER:
- break;
- case CALC_STATE_BRACKET:
- priorityQueues[CALC_PRIORITY_BRACKET].push_back(it);
- break;
- case CALC_STATE_VARIABLE:
- // TODO: X
- break;
- case CALC_STATE_ERROR:
- // Raise error
- break;
- }
- }
- for (std::vector<std::vector<CalculationElement>::iterator>::iterator it = priorityQueues[CALC_PRIORITY_BRACKET].begin(); it != priorityQueues[CALC_PRIORITY_BRACKET].end(); it++) {
- std::vector<CalculationElement> bracket = (*elementsVector)[(*it)->second];
- if (bracket.size() > 1 || (bracket.size() == 1 && bracket.begin()->first == CALC_STATE_BRACKET)) {
- calculateElements(&bracket, elementsVector);
- }
- if (bracket.size() == 1 && bracket.begin()->first == CALC_STATE_NUMBER) {
- (*it)->first = CALC_STATE_NUMBER;
- (*it)->second = bracket.begin()->second;
- } else {
- // Raise error
- }
- }
- for (std::vector<std::vector<CalculationElement>::iterator>::iterator it = priorityQueues[CALC_PRIORITY_FUNCTION].begin(); it != priorityQueues[CALC_PRIORITY_FUNCTION].end(); it++) {
- long double r;
- if ((*it)->second == 4) {
- r = sin((double)(*it + 1)->second);
- } else {
- r = -99; // TODO: replace that sus
- }
- elements->erase(*it, *it + 1);
- (*it)->first = CALC_STATE_NUMBER;
- (*it)->second = r;
- }
- for (std::vector<std::vector<CalculationElement>::iterator>::iterator it = priorityQueues[CALC_PRIORITY_UNARY].begin(); it != priorityQueues[CALC_PRIORITY_UNARY].end(); it++) {
- long double r = ((*it)->second == 1) ? (- (*it + 1)->second) : (*it + 1)->second;
- elements->erase(*it, *it + 1);
- (*it)->first = CALC_STATE_NUMBER;
- (*it)->second = r;
- (*it)--;
- }
- for (std::vector<std::vector<CalculationElement>::iterator>::iterator it = priorityQueues[CALC_PRIORITY_BINARY_0].begin(); it != priorityQueues[CALC_PRIORITY_BINARY_0].end(); it++) {
- std::vector<CalculationElement>::iterator it11 = (*it)-1;
- std::vector<CalculationElement>::iterator it12 = (*it)+1;
- long double r = ((*it)->second == 2) ? (((*it)-1)->second * ((*it)+1)->second) : (((*it)-1)->second / ((*it)+1)->second);
- (*it)--;
- elements->erase(*it, *it + 2);
- (*it)->first = CALC_STATE_NUMBER;
- (*it)->second = r;
- }
- for (std::vector<std::vector<CalculationElement>::iterator>::iterator it = priorityQueues[CALC_PRIORITY_BINARY_1].begin(); it != priorityQueues[CALC_PRIORITY_BINARY_1].end(); it++) {
- long double r = ((*it)->second == 0) ? (((*it)-1)->second + ((*it)+1)->second) : (((*it)-1)->second - ((*it)+1)->second);
- (*it)--;
- elements->erase(*it, *it + 2);
- (*it)->first = CALC_STATE_NUMBER;
- (*it)->second = r;
- }
- /*
- // Check brackets (and errors)
- for (std::vector<CalculationElement>::iterator it = elements->begin(); it != elements->end(); it++) {
- if (it->first == CALC_STATE_ERROR) {
- // Raise error
- // return 1;
- }
- if (it->first != CALC_STATE_BRACKET) continue;
- std::vector<CalculationElement> bracket = (*elementsVector)[it->second];
- if (bracket.size() > 1 || (bracket.size() == 1 && bracket.begin()->first == CALC_STATE_BRACKET)) {
- calculateElements(&bracket, elementsVector);
- } else if (bracket.size() == 1 && bracket.begin()->first == CALC_STATE_NUMBER) {
- it->first = CALC_STATE_NUMBER;
- it->second = bracket.begin()->second;
- } else {
- // Raise error
- }
- }
- // Check unary operations
- // Check **
- for (std::vector<CalculationElement>::iterator it = elements->begin(); it != elements->end(); it++) {
- if (it->first != CALC_STATE_OPERATION) continue;
- if (it->second != 4) continue;
- long double r = pow((double) (it - 1)->second, (double) (it + 1)->second);
- it--;
- elements->erase(it, it + 2);
- it->first = CALC_STATE_NUMBER;
- it->second = r;
- }
- // Check * and /
- for (std::vector<CalculationElement>::iterator it = elements->begin(); it != elements->end(); it++) {
- if (it->first != CALC_STATE_OPERATION) continue;
- if (it->second != 2 && it->second != 3) continue;
- long double r;
- switch ((int) it->second) {
- case 2:
- r = ((it - 1)->second * (it + 1)->second);
- break;
- case 3:
- r = ((it - 1)->second / (it + 1)->second);
- break;
- }
- it--;
- elements->erase(it, it + 2);
- it->first = CALC_STATE_NUMBER;
- it->second = r;
- }
- // Check + and -
- for (std::vector<CalculationElement>::iterator it = elements->begin(); it != elements->end(); it++) {
- std::cout << "deb: " << (int)it->first << " " << it->second << std::endl;
- if (it->first != CALC_STATE_OPERATION) continue;
- if (it->second != 0 && it->second != 1) continue;
- if (it == elements->begin() || (it-1)->first != CALC_STATE_NUMBER) {
- // Unary operation
- if (it->second == 1) {
- long double r = - (it+1)->second;
- elements->erase(it, it + 1);
- it->first = CALC_STATE_NUMBER;
- it->second = r;
- if (it != elements->begin()) {
- it -= 2;
- }
- }
- } else if ((it+1)->first == CALC_STATE_OPERATION) {
- continue;
- } else {
- // Binary operation
- long double r = (it->second == 0) ? ((it-1)->second + (it+1)->second) : ((it-1)->second - (it+1)->second);
- it--;
- elements->erase(it, it + 2);
- it->first = CALC_STATE_NUMBER;
- it->second = r;
- }
- }
- */
- return 0;
- }
- int main(const int argc, const char *argv[]) {
- std::vector<int> v;
- v.push_back(0);
- v.push_back(1);
- v.push_back(2);
- v.push_back(3);
- std::vector<int>::iterator it = v.begin() + 1;
- std::cout << "deb: " << *it << std::endl;
- v.erase(v.begin(), v.begin() + 1);
- std::cout << "deb: " << *it << std::endl;
- std::vector<std::vector<CalculationElement> > elements;
- std::vector<CalculationElement> element0;
- elements.push_back(element0);
- parseLine(&elements);
- for (std::vector<std::vector<CalculationElement> >::reverse_iterator it = elements.rbegin();
- it != elements.rend(); it++) {
- calculateElements(&*it, &elements);
- }
- long double result = elements.begin()->begin()->second;
- std::cout << "Result? " << result << std::endl;
- /*
- for (std::vector<CalculationElement>::iterator it = elements.begin(); it != elements.end(); it++) {
- std::cout << (int) it->first << " : " << it->second << std::endl;
- }
- */
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement