From cb5762a3fe493ba78134b2754dfcde3e80623d42 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 18 May 2025 16:17:14 -0500 Subject: [PATCH] Calculator works --- .../Calculator/Calculator.cpp | 281 ++++++++++++------ .../Calculator/Calculator.h | 3 + 2 files changed, 187 insertions(+), 97 deletions(-) diff --git a/modules/Archimedes-Modules/Calculator/Calculator.cpp b/modules/Archimedes-Modules/Calculator/Calculator.cpp index a9f67f1..abdb225 100644 --- a/modules/Archimedes-Modules/Calculator/Calculator.cpp +++ b/modules/Archimedes-Modules/Calculator/Calculator.cpp @@ -43,112 +43,199 @@ void Calculator::run() { } } + +void Calculator::index(std::string equation, std::unordered_map& nodes) { + unsigned int idx = 0; + + nodes.clear(); + + const static std::string operators[] = { + "(", + ")", + "^", + "*", + "/", + "+", + "-" + }; + + for(const std::string& s : operators) { + + while(equation.find(s, idx) != std::string::npos) { + int next = equation.find(s, idx); + nodes[next] = equation.substr(next, s.length()); + idx = next + s.length(); + } + idx = 0; + } + + + // -3+8*6-(8+4)^9/5 + for(unsigned int i = 0; i < equation.length(); i++) { + static unsigned int begin = 0, end = 0; + if(nodes.find(i) == nodes.end()) { + if(nodes.find(i - 1) != nodes.end() || i == 0) { + //first digit of expression + begin = i; + } + if(nodes.find(i + 1) != nodes.end() || i == equation.length() - 1) { + //character after last digit of expression + end = i + 1; + nodes[begin] = equation.substr(begin, end - begin); + nodes[end - 1] = equation.substr(begin, end - begin); + } + } + } +} + +double Calculator::evaluate(std::string equation, std::unordered_map& evalStr) { + + char op = '^'; + + while(equation.find(op) == std::string::npos) { + switch(op) { + case '^': + op = '*'; + break; + case '*': + op = '/'; + break; + case '/': + op = '+'; + break; + case '+': + op = '-'; + break; + case '-': + //no operator + if(evalStr.find(equation.front()) != evalStr.end()) { + return evaluate(evalStr[equation.front()], evalStr); + } else { + return std::stod(equation); + } + break; + } + } + //op is now the appropriate operator + + //if either term is a placeholder, evaluate and substitute. + double a, b; + if(evalStr.find(equation.front()) != evalStr.end()) { + a = evaluate(evalStr[equation.front()], evalStr); + } else { + if(equation.find(op) == 0 && op == '-') { + a = 0; + } else { + a = std::stod(equation.substr(0, equation.find(op))); + } + } + + if(evalStr.find(equation.back()) != evalStr.end()) { + b = evaluate(evalStr[equation.back()], evalStr); + } else { + b = std::stod(equation.substr(equation.find(op) + 1)); + } + switch(op) { + case '^': + return pow(a, b); + case '*': + return a * b; + case '/': + return a / b; + case '+': + return a + b; + case '-': + return a - b; + } +} std::string Calculator::calculate(std::string equation) { - std::stringstream s(equation); //PEMDAS - while(equation.find('(') != std::string::npos) { - if(equation.find(')') == std::string::npos) { - return "error"; - } - - int start = equation.find_last_of('('); - int end = equation.find(')', start); - - std::cout << "start with: " << equation.substr(start + 1, end - 2) << std::endl; - - std::string insert = calculate(equation.substr(start + 1, end - 2)); - - std::cout << "replace with: " << insert << std::endl; - - equation.replace(start - 1, (end + 1) - (start - 1), insert.c_str()); - + while(equation.find(' ') != std::string::npos) { + equation.erase(equation.find(' '), 1); } - while(equation.find('^') != std::string::npos) { + std::unordered_map nodes; + std::unordered_map evalStr; + std::string eval = "a"; + + unsigned int idx = 0; + + index(equation, nodes); + + idx = 0; + + // () + while(equation.find(')', idx) != std::string::npos) { + int end = equation.find(')'); + int begin = equation.rfind('(', end); + evalStr[eval.front()] = calculate(equation.substr(begin + 1, (end - begin) - 1)); + equation.replace(begin, (end - begin) + 1, eval); + eval.front()++; + idx = end + 1; + } + idx = 0; + index(equation, nodes); + // ^ + while(equation.find('^', idx) != std::string::npos) { int mid = equation.find('^'); - int lmid = mid - 2; - int rmid = mid + 2; - int start = equation.rfind(' ', lmid) == std::string::npos ? 0 : equation.rfind(' ', lmid) + 1; - int end = equation.find(' ', rmid) == std::string::npos ? equation.length() - 1 : equation.find(' ', rmid) - 1; - - - double a = stod(equation.substr(start, mid - 1 - start)); - double b = stod(equation.substr(rmid, end - (mid + 1))); - - std::string insert = std::to_string(pow(a, b)); - - equation.replace(start, end, insert.c_str()); - + int begin = equation.find(nodes[mid - 1] + nodes[mid]); + int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); + evalStr[eval.front()] = equation.substr(begin, end - begin); + equation.replace(begin, end - begin, eval); + eval.front()++; + idx = end + 1; } - while(equation.find('*') != std::string::npos) { - int mid = equation.find('*'); - int lmid = mid - 2; - int rmid = mid + 2; - int start = equation.rfind(' ', lmid) == std::string::npos ? 0 : equation.rfind(' ', lmid) + 1; - int end = equation.find(' ', rmid) == std::string::npos ? equation.length() - 1 : equation.find(' ', rmid) - 1; - - - double a = stod(equation.substr(start, mid - 1 - start)); - double b = stod(equation.substr(rmid, end - (mid + 1))); - - std::string insert = std::to_string(a * b); - - equation.replace(start, end, insert.c_str()); - + idx = 0; + index(equation, nodes); + // * or / + while(equation.find('*', idx) != std::string::npos || equation.find('/', idx) != std::string::npos) { + if(equation.find('*', idx) < equation.find('/', idx) && equation.find('*', idx) != std::string::npos) { + int mid = equation.find('*'); + int begin = equation.find(nodes[mid - 1] + nodes[mid]); + int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); + evalStr[eval.front()] = equation.substr(begin, end - begin); + equation.replace(begin, end - begin, eval); + eval.front()++; + idx = end + 1; + } else if(equation.find('/', idx) != std::string::npos) { + int mid = equation.find('/'); + int begin = equation.find(nodes[mid - 1] + nodes[mid]); + int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); + evalStr[eval.front()] = equation.substr(begin, end - begin); + equation.replace(begin, end - begin, eval); + eval.front()++; + idx = end + 1; + } } - while(equation.find('/') != std::string::npos) { - int mid = equation.find('/'); - int lmid = mid - 2; - int rmid = mid + 2; - int start = equation.rfind(' ', lmid) == std::string::npos ? 0 : equation.rfind(' ', lmid) + 1; - int end = equation.find(' ', rmid) == std::string::npos ? equation.length() - 1 : equation.find(' ', rmid) - 1; - - double a = stod(equation.substr(start, mid - 1 - start)); - double b = stod(equation.substr(rmid, end - (mid + 1))); - - std::string insert = std::to_string(a / b); - - equation.replace(start, end, insert.c_str()); - + idx = 0; + index(equation, nodes); + // + or - + while(equation.find('+', idx) != std::string::npos || equation.find('-', idx) != std::string::npos) { + if(equation.find('+', idx) < equation.find('-', idx) && equation.find('+', idx) != std::string::npos) { + int mid = equation.find('+'); + int begin = equation.find(nodes[mid - 1] + nodes[mid]); + int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); + evalStr[eval.front()] = equation.substr(begin, end - begin); + equation.replace(begin, end - begin, eval); + eval.front()++; + idx = end + 1; + } else if(equation.find('-', idx) != std::string::npos) { + int mid = equation.find('-'); + int begin = mid; + if(nodes.find(mid - 1) != nodes.end()) { + begin = equation.find(nodes[mid - 1] + nodes[mid]); + } + int end = equation.find(nodes[mid] + nodes[mid + 1], begin) + (nodes[mid] + nodes[mid + 1]).length(); + evalStr[eval.front()] = equation.substr(begin, end - begin); + equation.replace(begin, end - begin, eval); + eval.front()++; + idx = end + 1; + } } - while(equation.find('+') != std::string::npos) { - int mid = equation.find('+'); - int lmid = mid - 2; - int rmid = mid + 2; - - int start = equation.rfind(' ', lmid) == std::string::npos ? 0 : equation.rfind(' ', lmid) + 1; - int end = equation.find(' ', rmid) == std::string::npos ? equation.length() - 1 : equation.find(' ', rmid) - 1; - - std::cout << "a: " << equation.substr(start, mid - 1 - start) << std::endl; - std::cout << "b: " << equation.substr(rmid, end - (mid + 1)) << std::endl; - double a = stod(equation.substr(start, mid - 1 - start)); - double b = stod(equation.substr(rmid, end - (mid + 1))); - - std::string insert = std::to_string(a + b); - - equation.replace(start, end, insert.c_str()); - - } - while(equation.find('-') != std::string::npos) { - int mid = equation.find('-'); - int lmid = mid - 2; - int rmid = mid + 2; - - int start = equation.rfind(' ', lmid) == std::string::npos ? 0 : equation.rfind(' ', lmid) + 1; - int end = equation.find(' ', rmid) == std::string::npos ? equation.length() - 1 : equation.find(' ', rmid) - 1; - - double a = stod(equation.substr(start, mid - 1 - start)); - double b = stod(equation.substr(rmid, end - (mid + 1))); - - std::string insert = std::to_string(a - b); - - equation.replace(start, end, insert.c_str()); - - } - - return equation; + + return std::to_string(evaluate(equation, evalStr)); } @@ -167,7 +254,7 @@ void Calculator::basicCalculator() { ImGui::BeginGroup(); { if(ImGui::Button("AC")) { - s += " + "; + s.clear(); } ImGui::SameLine(); if(ImGui::Button("()")) { diff --git a/modules/Archimedes-Modules/Calculator/Calculator.h b/modules/Archimedes-Modules/Calculator/Calculator.h index 2e93391..a6b9bf9 100644 --- a/modules/Archimedes-Modules/Calculator/Calculator.h +++ b/modules/Archimedes-Modules/Calculator/Calculator.h @@ -22,8 +22,11 @@ class Calculator : public Archimedes::Module { void basicCalculator(); std::string calculate(std::string); + double evaluate(std::string, std::unordered_map&); + void index(std::string, std::unordered_map&); void graphingCalculator(); + }; #ifdef CALCULATOR_DYNAMIC