1
0
Fork 0
mirror of https://gitlab.com/mfocko/CodeWars.git synced 2024-11-09 11:09:07 +01:00
CodeWars/4kyu/infix_to_postfix_converter/solution.cpp
Matej Focko 54483a1651
4kyu: add infix to postfix converter
Signed-off-by: Matej Focko <mfocko@redhat.com>
2022-08-03 09:46:55 +02:00

108 lines
2.2 KiB
C++

#include <cassert>
#include <string>
#include <vector>
namespace {
template <typename T>
void pop_and_push(std::vector<T> &src, std::vector<T> &dst) {
assert(src.size());
dst.push_back(src.back());
src.pop_back();
}
int priority(char op) {
switch (op) {
case '(':
case ')':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '^':
return 3;
default:
assert(false);
}
}
enum assoc_t { LEFT, RIGHT, NONE };
assoc_t associativity(char op) {
assert(!std::isdigit(op));
switch (op) {
case '(':
case ')':
return assoc_t::NONE;
case '^':
return assoc_t::RIGHT;
default:
return assoc_t::LEFT;
}
}
bool pop_operator(std::vector<char> &op_stack, char o1) {
if (op_stack.empty()) {
return false;
}
char o2 = op_stack.back();
if (o2 == '(') {
return false;
}
int o1_priority = priority(o1);
int o2_priority = priority(o2);
return o2_priority > o1_priority ||
(o2_priority == o1_priority && associativity(o1) == assoc_t::LEFT);
}
} // namespace
std::string to_postfix(std::string infix) {
std::vector<char> output_queue;
std::vector<char> operator_stack;
for (char token : infix) {
if (std::isdigit(token)) {
output_queue.push_back(token);
} else if (token == '(') {
operator_stack.push_back(token);
} else if (token == ')') {
while (operator_stack.back() != '(') {
assert(operator_stack.size());
pop_and_push(operator_stack, output_queue);
}
assert(operator_stack.back() == '(');
operator_stack.pop_back();
} else {
while (pop_operator(operator_stack, token)) {
pop_and_push(operator_stack, output_queue);
}
operator_stack.push_back(token);
}
}
while (operator_stack.size()) {
assert(operator_stack.back() != '(');
pop_and_push(operator_stack, output_queue);
}
return std::string(output_queue.begin(), output_queue.end());
}
int main() {
assert(to_postfix("2+7*5") == "275*+");
assert(to_postfix("3*3/(7+1)") == "33*71+/");
assert(to_postfix("5+(6-2)*9+3^(7-1)") == "562-9*+371-^+");
assert(to_postfix("(5-4-1)+9/5/2-7/1/7") == "54-1-95/2/+71/7/-");
assert(to_postfix("1^2^3") == "123^^");
return 0;
}