Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <sstream>
- #include <vector>
- //FROM MY UTILITY HEADER
- template <typename T>
- T interpret_as(std::istream& in)
- {
- auto out = T{};
- in >> out;
- return out;
- }
- template <typename T>
- T interpret_as(const std::string& in)
- {
- auto stream = std::istringstream{ in };
- return interpret_as<T>(stream);
- }
- template <>
- std::string interpret_as<std::string>(const std::string& in)
- {
- return in;
- }
- template <typename T>
- T interpret_line_as(std::istream& in)
- {
- auto str = string{};
- getline(in, str);
- return interpret_as<T>(str);
- }
- enum BracketType
- {
- NOT_BRACKET = 0,
- OPEN_BRACKET = 1,
- CLOSE_BRACKET = 2
- };
- BracketType isbracket(char ch)
- {
- const auto brackets = std::string{ "()[]{}" };
- const auto result = brackets.find(ch);
- if (result == brackets.npos)
- {
- return NOT_BRACKET;
- }
- return static_cast<BracketType>(1 + (result % 2));
- }
- // END FUNCTIONS FROM UTILITY
- using namespace std; // Toy projects only
- enum class Direction : char
- {
- left,
- right
- };
- typedef pair<char, Direction> Operator;
- template <>
- Direction interpret_as<Direction>(const string& in)
- {
- return (in == "left" ? Direction::left : Direction::right);
- }
- template <>
- Operator interpret_as<Operator>(const string& in)
- {
- return Operator{ in.at(0), interpret_as<Direction>(in.substr(2)) };
- }
- int distanceToCloseBracket(const string& expression)
- {
- for (auto it = begin(expression)+1; it != end(expression); ++it)
- {
- switch (isbracket(*it))
- {
- default:
- case NOT_BRACKET:
- break;
- case CLOSE_BRACKET:
- return distance(begin(expression),it);
- break;
- case OPEN_BRACKET:
- it += distanceToCloseBracket(string{ it, end(expression) });
- break;
- }
- }
- return 0;
- }
- int findCharLtoR(const string& expression, char ch)
- {
- // Search, ignoring anywhere inside brackets.
- auto openBrackets = 0;
- for (auto it = begin(expression); it != end(expression); ++it)
- {
- if (isbracket(*it))
- {
- // Skip to the end of the brackets.
- it += distanceToCloseBracket(string{ it, end(expression) });
- }
- if (*it == ch)
- {
- return distance(begin(expression),it);
- }
- }
- return -1;
- }
- int findCharRtoL(const string& expression, char ch)
- {
- auto reversedExpression = string{rbegin(expression), rend(expression)};
- // Reverse the brackets.
- for (auto& ch : reversedExpression)
- {
- if (isbracket(ch) == OPEN_BRACKET)
- {
- ch = ')';
- }
- if (isbracket(ch) == CLOSE_BRACKET)
- {
- ch = '(';
- }
- }
- // Hook into the LtoR finder.
- const auto result = findCharLtoR(reversedExpression, ch);
- // Convert the result.
- if (result == -1)
- {
- return result;
- }
- else
- {
- return static_cast<int>(expression.size()) - 1 - result;
- }
- }
- int findOperator(const string& expression, const Operator& op)
- {
- return (op.second == Direction::right ? findCharLtoR(expression, op.first) : findCharRtoL(expression, op.first));
- }
- string parseExpression(const string& expression, const vector<Operator>& operators)
- {
- // Search the operators backwards, so we start from the lowest precedence.
- for (auto it = rbegin(operators); it != rend(operators); ++it)
- {
- // If an operator is found, split around that operator, and parse the two sides separately.
- const auto pos = findOperator(expression, *it);
- if (pos != -1)
- {
- const auto leftSide = expression.substr(0, pos);
- const auto rightSide = expression.substr(pos + 1);
- auto output = ostringstream{};
- output << '(' << parseExpression(leftSide, operators)
- << it->first
- << parseExpression(rightSide, operators) << ')';
- return output.str();
- }
- }
- // If no operator, seek out brackets and parse into the brackets.
- auto output = ostringstream{};
- for (auto it = begin(expression); it != end(expression); ++it)
- {
- output << *it;
- if (isbracket(*it) == OPEN_BRACKET)
- {
- auto startPoint = it + 1;
- it += distanceToCloseBracket(string{ it, end(expression) });
- auto endPoint = it;
- output << parseExpression(string{ startPoint, endPoint }, operators);
- }
- }
- return output.str();
- }
- int main()
- {
- const auto n_operators = interpret_line_as<int>(cin);
- auto operators = vector<Operator>{};
- operators.reserve(n_operators);
- for (auto i = 0; i < n_operators; ++i)
- {
- operators.push_back(interpret_line_as<Operator>(cin));
- }
- const auto expression = interpret_line_as<string>(cin);
- cout << parseExpression(expression, operators) << '\n';
- cin.get();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement