some programs!!
This commit is contained in:
1 parent
ed054247d5
commit
71f1022dea
38 files changed
+1037
-281
No files matched your search
@@ -0,0 +1,137 @@
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <stack>
|
||||
|
||||
|
||||
struct Token {
|
||||
std::variant<char, int> token;
|
||||
|
||||
explicit Token(char c) : token(c) {}
|
||||
explicit Token(int x) : token(x) {}
|
||||
|
||||
[[nodiscard]] bool is_operator() const {
|
||||
return std::holds_alternative<char>(token);
|
||||
}
|
||||
|
||||
[[nodiscard]] char get_operator() const {
|
||||
if (!is_operator()) { throw std::invalid_argument("Not an operator"); }
|
||||
return std::get<char>(token);
|
||||
}
|
||||
|
||||
[[nodiscard]] int get_number() const {
|
||||
if (is_operator()) { throw std::invalid_argument("Is an operator"); }
|
||||
return std::get<int>(token);
|
||||
}
|
||||
|
||||
bool operator==(char c) const {
|
||||
if (!is_operator()) { return false; }
|
||||
return get_operator() == c;
|
||||
}
|
||||
|
||||
bool operator==(int x) const {
|
||||
if (is_operator()) { return false; }
|
||||
return get_number() == x;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(T x) {
|
||||
return !(*this == x);
|
||||
}
|
||||
};
|
||||
|
||||
using Expression = std::vector<Token>;
|
||||
|
||||
Expression parse_string(const std::string& str) {
|
||||
Expression expression;
|
||||
std::string temp_token;
|
||||
for (char c : str) {
|
||||
if (!(c > '0' && c < '9')) {
|
||||
if (!temp_token.empty()) {
|
||||
expression.emplace_back(std::stoi(temp_token));
|
||||
temp_token.clear();
|
||||
}
|
||||
expression.emplace_back(c);
|
||||
} else {
|
||||
temp_token += c;
|
||||
}
|
||||
}
|
||||
if (!temp_token.empty()) { expression.emplace_back(std::stoi(temp_token)); }
|
||||
return expression;
|
||||
}
|
||||
|
||||
void calculate_chunk(std::stack<Token>& undealt_tokens, std::stack<Token>& ready_tokens) {
|
||||
while (!undealt_tokens.empty() && undealt_tokens.top() != '(') {
|
||||
ready_tokens.push(undealt_tokens.top());
|
||||
undealt_tokens.pop();
|
||||
}
|
||||
int temp_result = ready_tokens.top().get_number();
|
||||
ready_tokens.pop();
|
||||
while (!ready_tokens.empty()) {
|
||||
char op = ready_tokens.top().get_operator();
|
||||
ready_tokens.pop();
|
||||
if (op == '+') {
|
||||
temp_result += ready_tokens.top().get_number();
|
||||
} else if (op == '-') {
|
||||
temp_result -= ready_tokens.top().get_number();
|
||||
} else {
|
||||
throw std::logic_error("Unexpected operator token in chunk.");
|
||||
}
|
||||
ready_tokens.pop();
|
||||
}
|
||||
if (!undealt_tokens.empty()) {
|
||||
undealt_tokens.pop();
|
||||
}
|
||||
undealt_tokens.emplace(temp_result);
|
||||
}
|
||||
|
||||
int calculate(const Expression& expression) {
|
||||
// 策略:
|
||||
// 遇到 * / 直接算(本质上是把上一个子 expression 倒栈)
|
||||
// 遇到右括号 / 结尾开始倒栈
|
||||
// 对于倒栈,只剩下 +- 需要处理。
|
||||
std::stack<Token> undealt_tokens, ready_tokens;
|
||||
std::optional<Token> temp_token;
|
||||
|
||||
for (const auto& token : expression) {
|
||||
if (token == '*' || token == '/') {
|
||||
temp_token = token;
|
||||
continue;
|
||||
}
|
||||
if (temp_token.has_value()) {
|
||||
int a = undealt_tokens.top().get_number();
|
||||
undealt_tokens.pop();
|
||||
undealt_tokens.emplace(
|
||||
temp_token == '*' ? a * token.get_number() : a / token.get_number()
|
||||
);
|
||||
temp_token.reset();
|
||||
continue;
|
||||
}
|
||||
if (token == ')') {
|
||||
calculate_chunk(undealt_tokens, ready_tokens);
|
||||
continue;
|
||||
}
|
||||
undealt_tokens.push(token);
|
||||
}
|
||||
calculate_chunk(undealt_tokens, ready_tokens);
|
||||
assert(undealt_tokens.size() == 1);
|
||||
return undealt_tokens.top().get_number();
|
||||
}
|
||||
|
||||
int n;
|
||||
std::string s;
|
||||
|
||||
int main() {
|
||||
std::ios::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
std::cin >> n;
|
||||
for (int _ = 0; _ < n; _++) {
|
||||
std::cin >> s;
|
||||
std::cout << calculate(parse_string(s)) << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user