Initial commit
This commit is contained in:
149
2020/puzzle-18-02.cc
Normal file
149
2020/puzzle-18-02.cc
Normal file
@@ -0,0 +1,149 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
enum class Token : char {
|
||||
Eof,
|
||||
Number,
|
||||
LParens = '(',
|
||||
RParens = ')',
|
||||
Add = '+',
|
||||
Multiply = '*'
|
||||
};
|
||||
using Value = unsigned long;
|
||||
|
||||
struct Parser {
|
||||
Parser(std::string const &s) : expr_(s), pos_(0) { skip_whitespace(); }
|
||||
|
||||
Value evaluate() { return multop(); }
|
||||
|
||||
private:
|
||||
Value addop() {
|
||||
auto value = primary();
|
||||
do {
|
||||
if (peek() == Token::Add) {
|
||||
chew(Token::Add);
|
||||
value += primary();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Value multop() {
|
||||
auto value = addop();
|
||||
do {
|
||||
if (peek() == Token::Multiply) {
|
||||
chew(Token::Multiply);
|
||||
value *= addop();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Value primary() {
|
||||
if (peek() == Token::LParens) {
|
||||
chew(Token::LParens);
|
||||
Value value = evaluate();
|
||||
chew(Token::RParens);
|
||||
return value;
|
||||
} else if (peek() == Token::Number) {
|
||||
return chew_number();
|
||||
} else {
|
||||
std::cout << "expr_ = " << expr_ << "\n";
|
||||
std::cout << "pos_ = " << pos_ << "\n";
|
||||
std::cout << "End = " << expr_.substr(pos_) << "\n";
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
Token peek() {
|
||||
if (pos_ == expr_.size()) {
|
||||
return Token::Eof;
|
||||
}
|
||||
switch (expr_[pos_]) {
|
||||
case '(':
|
||||
return Token::LParens;
|
||||
case ')':
|
||||
return Token::RParens;
|
||||
case '+':
|
||||
return Token::Add;
|
||||
case '*':
|
||||
return Token::Multiply;
|
||||
case '-':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return Token::Number;
|
||||
default:
|
||||
std::cout << "expr_ = " << expr_ << "\n";
|
||||
std::cout << "pos_ = " << pos_ << "\n";
|
||||
std::cout << "End = " << expr_.substr(pos_) << "\n";
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void chew(Token tok) {
|
||||
assert(peek() == tok);
|
||||
switch (tok) {
|
||||
case Token::LParens:
|
||||
case Token::RParens:
|
||||
case Token::Add:
|
||||
case Token::Multiply:
|
||||
++pos_;
|
||||
skip_whitespace();
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
void skip_whitespace() {
|
||||
while (pos_ < expr_.size() && expr_[pos_] == ' ') {
|
||||
++pos_;
|
||||
}
|
||||
}
|
||||
|
||||
Value chew_number() {
|
||||
assert(peek() == Token::Number);
|
||||
|
||||
std::size_t len = 0;
|
||||
Value value = std::stoul(expr_.substr(pos_), &len);
|
||||
pos_ += len;
|
||||
skip_whitespace();
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string expr_;
|
||||
std::string::size_type pos_;
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
std::string line;
|
||||
Value result = 0;
|
||||
while (std::getline(std::cin, line)) {
|
||||
Parser p(line);
|
||||
Value r = p.evaluate();
|
||||
std::cout << line << " = " << r << "\n";
|
||||
result += r;
|
||||
}
|
||||
|
||||
std::cout << "Sum: " << result << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user