### Counting nums

I was thinking to convert A~E in string into corresponding numbers then do the calculations, while the code shows wrong answer.

You have an arithmetic expression that contains at most 5 variables A - E and operators +, -, *, /, (, ), where the / denotes integer division. Given the values for the variables, please calculate the answer.

Input Format

The first line is the arithmetic expression.

The second line is an integer T.

In the following T lines, each line has 5 integers: the values for variable A to E.

Output Format

Output T lines, each line is the answer to a set of values for variable A to E.
 ``12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273`` ``````#include #include #include #include #include #include #include #include #include using namespace std; class Solution { public: int calculate(string s) { vector nums; char op = '+'; long unsigned int cur = 0; long unsigned int pos = 0; while (pos < s.size()) { if (s[pos] == ' ') { ++pos; continue; } while (isdigit(s[pos]) && pos < s.size()) cur = cur * 10 + (s[pos++] - '0'); if (op == '+' || op == '-') { nums.push_back(cur * (op == '+' ? 1 : -1)); } else if (op == '*') { nums.back() *= cur; } else if (op == '/') { nums.back() /= cur; } cur = 0; op = s[pos++]; } return accumulate(begin(nums), end(nums), 0); } }; void findAndReplaceAll(std::string & data, std::string toSearch, std::string replaceStr) { size_t pos = data.find(toSearch); // Repeat till end is reached while( pos != std::string::npos) { data.replace(pos, toSearch.size(), replaceStr); pos =data.find(toSearch, pos + replaceStr.size()); } } int main() { string str,res; int t,a,b,c,d,e; cin>>str>>t; while(t--) { cin>>a>>b>>c>>d>>e; findAndReplaceAll(str, "A", "a"); findAndReplaceAll(str, "B", "b"); findAndReplaceAll(str, "C", "c"); findAndReplaceAll(str, "D", "d"); findAndReplaceAll(str, "E", "e"); Solution sol; cout<
Last edited on
Where is str set to the expression to calculate?

How are you dealing with parentheses () ?

How are you evaluating the letters A - E to numbers to be used? L63-67 just replaces all occurrences of A - E with the letters a - e (not their values)??
Last edited on
Thanks for your advice, I've modified the code, while it shows run time error.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384`` ``````#include #include #include #include #include #include #include #include #include using namespace std; class Solution { public: long unsigned int calculate(string s) { long unsigned int n = s.size(), num = 0, curRes = 0, res = 0; char op = '+'; for (long unsigned int i = 0; i < n; ++i) { char c = s[i]; if (c >= '0' && c <= '9') { num = num * 10 + c - '0'; } else if (c == '(') { int j = i, cnt = 0; for (; i < n; ++i) { if (s[i] == '(') ++cnt; if (s[i] == ')') --cnt; if (cnt == 0) break; } num = calculate(s.substr(j + 1, i - j - 1)); } if (c == '+' || c == '-' || c == '*' || c == '/' || i == n - 1) { switch (op) { case '+': curRes += num; break; case '-': curRes -= num; break; case '*': curRes *= num; break; case '/': curRes /= num; break; } if (c == '+' || c == '-' || i == n - 1) { res += curRes; curRes = 0; } op = c; num = 0; } } return res; } }; string changeVar(string startingExpr, char var, int val) { for(long unsigned int i = 0; i < startingExpr.length(); i++) { if(startingExpr[i] == var) { startingExpr[i] = '0' + val; } } return startingExpr; } int main() { string str; long unsigned int t,a,b,c,d,e; cin>>str; cin>>t; while(t--) { cin>>a>>b>>c>>d>>e; changeVar(str, 'A', a); changeVar(str, 'B', b); changeVar(str, 'C', c); changeVar(str, 'D', d); changeVar(str, 'E', e); Solution sol; cout<
Last edited on
Within changeVar, how is a variable value > 9 dealt with? If say the value is 12, then '0' + 12 gives '<' whereas you want '12'.

Also, changeVar returns the adjusted string value, but this return value isn't used by by the caller. Note that as startingExpr is passed by value, changes to startingExpr within the function aren't reflected back in the caller.
Why would it become '<' ? What would be a better suggestion, should I convert the arithmetic expression into a postfix first?
I would. I also wouldn't convert the letters to numbers within the string first but use a look up when the expression is evaluated.

 Why would it become '<' ?

Using ASCII, '0' + 12 is 48 + 12 which is 60 which is '<'
Noted thank you. Here I want to ask how to achieve the look up from char to the input number after function infixToPostfix().

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127`` ``````#include #include #include #include #include #include using namespace std; int prec(char c) { if (c == '^') return 3; else if (c == '/' || c == '*') return 2; else if (c == '+' || c == '-') return 1; else return -1; } void infixToPostfix(string s) { stack st; string result; for (int i = 0; i < s.length(); i++) { char c = s[i]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) result += c; else if (c == '(') st.push('('); else if (c == ')') { while (st.top() != '(') { result += st.top(); st.pop(); } st.pop(); } else { while (!st.empty() && prec(s[i]) <= prec(st.top())) { if (c == '^' && st.top() == '^') break; else { result += st.top(); st.pop(); } } st.push(c); } } while (!st.empty()) { result += st.top(); st.pop(); } } int calculate_Postfix(string post_exp) { stack stack; int len = post_exp.length(); // loop to iterate through the expression for (int i = 0; i < len; i++) { // if the character is an operand we push it in the stack // we have considered single digits only here if ( post_exp[i] >= '0' && post_exp[i] <= '9') { stack.push( post_exp[i] - '0'); } // if the character is an operator we enter else block else { // we pop the top two elements from the stack and save them in two integers int a = stack.top(); stack.pop(); int b = stack.top(); stack.pop(); //performing the operation on the operands switch (post_exp[i]) { case '+': stack.push(b + a); break; case '-': stack.push(b - a); break; case '*': stack.push(b * a); break; case '/': stack.push(b / a); break; } } } return stack.top(); } int main() { string str; long unsigned int t,a,b,c,d,e; cin>>str; cin>>t; while(t--) { cin>>a>>b>>c>>d>>e; infixToPostfix(str); cout<
Last edited on
Maybe this, which also deals with numeric numbers with more than 1 digit. Note, though, there is no error checking for an invalid expression:

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134`` ``````#include #include #include #include #include #include using Vars = int [5]; int prec(char c) { if (c == '^') return 3; else if (c == '/' || c == '*') return 2; else if (c == '+' || c == '-') return 1; else return -1; } std::string infixToPostfix(const std::string& s) { std::stack st; std::string result; for (size_t i {}; i < s.length(); ++i) { const char& c {s[i]}; if (c == ' ') continue; if (c >= 'a' && c <= 'e') result += c; else if (c >= 'A' && c <= 'E') result += c - ('a' - 'A'); else if (c >= '0' && c <= '9') { while (s[i] >= '0' && s[i] <= '9') result += s[i++]; result += ' '; --i; } else if (c == '(') st.push('('); else if (c == ')') { while (st.top() != '(') { result += st.top(); st.pop(); } st.pop(); } else { while (!st.empty() && prec(s[i]) <= prec(st.top())) { if (c == '^' && st.top() == '^') break; else { result += st.top(); st.pop(); } } st.push(c); } } while (!st.empty()) { result += st.top(); st.pop(); } return result; } int calculate_Postfix(const std::string& post_exp, const Vars& vars) { std::stack stack; // loop to iterate through the expression for (size_t i {}; i < post_exp.length(); ++i) { const auto& ch {post_exp[i]}; // if the character is an operand we push it in the stack // we have considered single digits only here if (ch >= '0' && ch <= '9') { auto j {i}; int num {}; while (post_exp[j] >= '0' && post_exp[j] <= '9') ++j; std::from_chars(post_exp.data() + i, post_exp.data() + j, num); stack.push(num); i = j; } else if (ch >= 'a' && ch <= 'e') stack.push(vars[ch - 'a']); // if the character is an operator we enter else block else { // we pop the top two elements from the stack and save them in two integers const int a {stack.top()}; stack.pop(); const int b {stack.top()}; stack.pop(); //performing the operation on the operands switch (ch) { case '+': stack.push(b + a); break; case '-': stack.push(b - a); break; case '*': stack.push(b * a); break; case '/': stack.push(b / a); break; } } } return stack.top(); } int main() { std::string str; long unsigned t {}; Vars vars; std::getline(std::cin, str); std::cin >> t; while (t--) { std::cin >> vars[0] >> vars[1] >> vars[2] >> vars[3] >> vars[4]; std::cout << calculate_Postfix(infixToPostfix(str), vars); //std::cout << infixToPostfix(str) << '\n'; } }``````

 ``` a + b + 22 1 1 2 3 4 5 6 25 ```

Last edited on
I tried the code and it shows segmentation fault.
 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131`` ``````#include #include #include #include #include #include using Vars = int [5]; int prec(char c) { if (c == '^') return 3; else if (c == '/' || c == '*') return 2; else if (c == '+' || c == '-') return 1; else return -1; } std::string infixToPostfix(const std::string& s) { std::stack st; std::string result; for (size_t i {}; i < s.length(); ++i) { const char& c {s[i]}; if (c == ' ') continue; if (c >= 'a' && c <= 'e') result += c; else if (c >= 'A' && c <= 'E') result += c - ('a' - 'A'); else if (c >= '0' && c <= '9') { while (s[i] >= '0' && s[i] <= '9') result += s[i++]; result += ' '; --i; } else if (c == '(') st.push('('); else if (c == ')') { while (st.top() != '(') { result += st.top(); st.pop(); } st.pop(); } else { while (!st.empty() && prec(s[i]) <= prec(st.top())) { if (c == '^' && st.top() == '^') break; else { result += st.top(); st.pop(); } } st.push(c); } } while (!st.empty()) { result += st.top(); st.pop(); } return result; } int calculate_Postfix(const std::string& post_exp, const Vars& vars) { std::stack stack; for (size_t i {}; i < post_exp.length(); ++i) { const auto& ch {post_exp[i]}; if (ch >= '0' && ch <= '9') { auto j {i}; int num {}; while (post_exp[j] >= '0' && post_exp[j] <= '9') ++j; std::from_chars(post_exp.data() + i, post_exp.data() + j, num); stack.push(num); i = j; } else if (ch >= 'a' && ch <= 'e') stack.push(vars[ch - 'a']); else { const int a {stack.top()}; stack.pop(); const int b {stack.top()}; stack.pop(); switch (ch) { case '+': stack.push(b + a); break; case '-': stack.push(b - a); break; case '*': stack.push(b * a); break; case '/': stack.push(b / a); break; } } } return stack.top(); } int main() { std::string str; long unsigned t {}; Vars vars; std::getline(std::cin, str); std::cin >> t; while (t--) { std::cin >> vars[0] >> vars[1] >> vars[2] >> vars[3] >> vars[4]; std::cout << calculate_Postfix(infixToPostfix(str), vars); } }``````

With what input? If the input is invalid, all bets are off as there's no error checking.

Note that infixToPostfix() allows ^ (for power to?), but calculate_Postfix doesn't compute ^ !
Last edited on
With some simple error checking and ^ implemented, then perhaps as below. If this still causes a run-time error, what input is being used?

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164`` ``````#include #include #include #include #include #include #include using Vars = int[5]; int prec(char c) { if (c == '^') return 3; else if (c == '/' || c == '*') return 2; else if (c == '+' || c == '-') return 1; else return -1; } std::string infixToPostfix(const std::string& s) { std::stack st; std::string result; int par {}; for (size_t i {}; i < s.length(); ++i) { const char& c {s[i]}; if (c == ' ') continue; if ((c >= 'a' && c <= 'e') || (c >= 'A' && c <= 'E')) { if (i && (s[i - 1] >= 'a' && s[i - 1] <= 'e')) { std::cout << "Invalid variable\n"; result.clear(); return result; } result += (c >= 'a' && c <= 'e') ? c : c - ('a' - 'A'); } else if (c >= '0' && c <= '9') { while (s[i] >= '0' && s[i] <= '9') result += s[i++]; result += ' '; --i; } else if (c == '(') { st.push('('); ++par; } else if (c == ')') { --par; while (st.top() != '(') { result += st.top(); st.pop(); } st.pop(); } else { const auto p {prec(c)}; if (p < 0) { std::cout << "Invalid symbol " << c << '\n'; result.clear(); return result; } while (!st.empty() && p <= prec(st.top())) { // WHY?? //if (c == '^' && st.top() == '^') //break; //else { result += st.top(); st.pop(); //} } st.push(c); } } if (par) { std::cout << "Unmatched ()\n"; result.clear(); } else while (!st.empty()) { result += st.top(); st.pop(); } return result; } int calculate_Postfix(const std::string& post_exp, const Vars& vars) { std::stack stack; // loop to iterate through the expression for (size_t i {}; i < post_exp.length(); ++i) { const auto& ch {post_exp[i]}; // if the character is an operand we push it in the stack // we have considered single digits only here if (ch >= '0' && ch <= '9') { auto j {i}; int num {}; while (post_exp[j] >= '0' && post_exp[j] <= '9') ++j; std::from_chars(post_exp.data() + i, post_exp.data() + j, num); stack.push(num); i = j; } else if (ch >= 'a' && ch <= 'e') stack.push(vars[ch - 'a']); // if the character is an operator we enter else block else { // we pop the top two elements from the stack and save them in two integers const int a {stack.top()}; stack.pop(); const int b {stack.top()}; stack.pop(); //performing the operation on the operands switch (ch) { case '+': stack.push(b + a); break; case '-': stack.push(b - a); break; case '*': stack.push(b * a); break; case '/': stack.push(b / a); break; case '^': stack.push(static_cast(std::pow(b, a))); break; } } } return !stack.empty() ? stack.top() : 0; } int main() { std::string str; long unsigned t {}; Vars vars {1, 2, 3, 4, 5}; std::getline(std::cin, str); //std::cin >> t; //while (t--) { //std::cin >> vars[0] >> vars[1] >> vars[2] >> vars[3] >> vars[4]; std::cout << calculate_Postfix(infixToPostfix(str), vars); //std::cout << infixToPostfix(str) << '\n'; //} }``````

Last edited on
Inputs being used are :
A+B*(C-D)/E
2
4 8 7 6 3
5 7 3 4 1
so it shouldn't be invalid perhaps.
Sorry. Typing error. L40 c - should be c +. I only tested with lc letters!

This version also adds some extra checking on closing without opening brackets (ie check stack not empty before accessing).

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175`` ``````#include #include #include #include #include #include #include using Vars = int[5]; int prec(char c) { if (c == '^') return 3; else if (c == '/' || c == '*') return 2; else if (c == '+' || c == '-') return 1; else return -1; } std::string infixToPostfix(const std::string& s) { std::stack st; std::string result; int par {}; for (size_t i {}; i < s.length(); ++i) { const char& c {s[i]}; if (c == ' ') continue; if ((c >= 'a' && c <= 'e') || (c >= 'A' && c <= 'E')) { if (i && (s[i - 1] >= 'a' && s[i - 1] <= 'e')) { std::cout << "Invalid variable\n"; result.clear(); return result; } result += (c >= 'a' && c <= 'e') ? c : c + ('a' - 'A'); } else if (c >= '0' && c <= '9') { while (s[i] >= '0' && s[i] <= '9') result += s[i++]; result += ' '; --i; } else if (c == '(') { st.push('('); ++par; } else if (c == ')') { --par; if (st.empty()) { std::cout << "Closing without opening\n"; result.clear(); return result; } while (st.top() != '(') { result += st.top(); st.pop(); if (st.empty()) { std::cout << "Closing without opening\n"; result.clear(); return result; } } st.pop(); } else { const auto p {prec(c)}; if (p < 0) { std::cout << "Invalid symbol " << c << '\n'; result.clear(); return result; } while (!st.empty() && p <= prec(st.top())) { // WHY?? //if (c == '^' && st.top() == '^') //break; //else { result += st.top(); st.pop(); //} } st.push(c); } } if (par) { std::cout << "Unmatched ()\n"; result.clear(); } else while (!st.empty()) { result += st.top(); st.pop(); } return result; } int calculate_Postfix(const std::string& post_exp, const Vars& vars) { std::stack stack; // loop to iterate through the expression for (size_t i {}; i < post_exp.length(); ++i) { const auto& ch {post_exp[i]}; // if the character is an operand we push it in the stack // we have considered single digits only here if (ch >= '0' && ch <= '9') { auto j {i}; int num {}; while (post_exp[j] >= '0' && post_exp[j] <= '9') ++j; std::from_chars(post_exp.data() + i, post_exp.data() + j, num); stack.push(num); i = j; } else if (ch >= 'a' && ch <= 'e') stack.push(vars[ch - 'a']); // if the character is an operator we enter else block else { // we pop the top two elements from the stack and save them in two integers const int a {stack.top()}; stack.pop(); const int b {stack.top()}; stack.pop(); //performing the operation on the operands switch (ch) { case '+': stack.push(b + a); break; case '-': stack.push(b - a); break; case '*': stack.push(b * a); break; case '/': stack.push(b / a); break; case '^': stack.push(static_cast(std::pow(b, a))); break; } } } return !stack.empty() ? stack.top() : 0; } int main() { std::string str; long unsigned t {}; Vars vars {1, 2, 3, 4, 5}; std::getline(std::cin, str); std::cin >> t; while (t--) { std::cin >> vars[0] >> vars[1] >> vars[2] >> vars[3] >> vars[4]; std::cout << "res = " << calculate_Postfix(infixToPostfix(str), vars) << '\n'; //std::cout << infixToPostfix(str) << '\n'; } }``````

 ``` A+B*(C-D)/E 2 4 8 7 6 3 res = 6 5 7 3 4 1 res = -2 ```

Topic archived. No new replies allowed.