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
- /*
- 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;
- CalculationElement parseOperation(const std::string &operation) {
- static std::map<std::string, long double> operations;
- operations["+"] = 0;
- operations["-"] = 1;
- operations["*"] = 2;
- operations["/"] = 3;
- operations["**"] = 4;
- operations["pow"] = 4;
- std::map<std::string, long double>::iterator findIt = operations.find(operation);
- if (findIt != operations.end())
- return CalculationElement(CALC_STATE_OPERATION, findIt->second);
- // 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:
- 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
- }
- }
- // 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 ** and * 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 && it->second != 4) 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;
- case 4:
- r = pow((double) (it - 1)->second, (double) (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--;
- }
- }
- } 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<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