LeetCode Solutions
736. Parse Lisp Expression
Time: Space:
class Solution {
public:
int evaluate(string expression) {
return evaluate(expression, unordered_map<string, int>());
}
private:
int evaluate(const string& e, unordered_map<string, int> scope) {
if (isdigit(e[0]) || e[0] == '-')
return stoi(e);
if (scope.count(e))
return scope[e];
const int spaceIndex = e.find_first_of(' ');
const string nextExpression =
e.substr(spaceIndex + 1, e.length() - spaceIndex - 2); // -2: "()"
const vector<string> tokens = split(nextExpression);
// Note that e[0] == '('
if (e[1] == 'm') // Mult
return evaluate(tokens[0], scope) * evaluate(tokens[1], scope);
if (e[1] == 'a') // Add
return evaluate(tokens[0], scope) + evaluate(tokens[1], scope);
// Let
for (int i = 0; i + 1 < tokens.size(); i += 2)
scope[tokens[i]] = evaluate(tokens[i + 1], scope);
return evaluate(tokens.back(), scope);
};
vector<string> split(const string& e) {
vector<string> tokens;
string s;
int parenthesis = 0;
for (const char c : e) {
if (c == '(')
++parenthesis;
else if (c == ')')
--parenthesis;
if (parenthesis == 0 && c == ' ') {
tokens.push_back(s);
s = "";
} else {
s += c;
}
}
if (!s.empty())
tokens.push_back(s);
return tokens;
}
};
class Solution {
public int evaluate(String expression) {
return evaluate(expression, new HashMap<>());
}
private int evaluate(final String e, Map<String, Integer> prevScope) {
if (Character.isDigit(e.charAt(0)) || e.charAt(0) == '-')
return Integer.parseInt(e);
if (prevScope.containsKey(e))
return prevScope.get(e);
Map<String, Integer> scope = new HashMap<>();
scope.putAll(prevScope);
final int spaceIndex = e.indexOf(' ');
final String nextExpression = e.substring(spaceIndex + 1, e.length() - 1); // -2: "()"
List<String> tokens = split(nextExpression);
if (e.startsWith("(m")) // Mult
return evaluate(tokens.get(0), scope) * evaluate(tokens.get(1), scope);
if (e.startsWith("(a")) // Add
return evaluate(tokens.get(0), scope) + evaluate(tokens.get(1), scope);
// Let
for (int i = 0; i < tokens.size() - 2; i += 2)
scope.put(tokens.get(i), evaluate(tokens.get(i + 1), scope));
return evaluate(tokens.get(tokens.size() - 1), scope);
}
private List<String> split(final String s) {
List<String> tokens = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int parenthesis = 0;
for (char c : s.toCharArray()) {
if (c == '(')
++parenthesis;
else if (c == ')')
--parenthesis;
if (parenthesis == 0 && c == ' ') {
tokens.add(sb.toString());
sb.setLength(0);
} else {
sb.append(c);
}
}
if (sb.length() > 0)
tokens.add(sb.toString());
return tokens;
}
}
class Solution:
def evaluate(self, expression: str) -> int:
def evaluate(e: str, prevScope: dict) -> int:
if e[0].isdigit() or e[0] == '-':
return int(e)
if e in prevScope:
return prevScope[e]
scope = prevScope.copy()
nextExpression = e[e.index(' ') + 1:-1]
tokens = parse(nextExpression)
if e[1] == 'a':
return evaluate(tokens[0], scope) + evaluate(tokens[1], scope)
if e[1] == 'm':
return evaluate(tokens[0], scope) * evaluate(tokens[1], scope)
for i in range(0, len(tokens) - 2, 2):
scope[tokens[i]] = evaluate(tokens[i + 1], scope)
return evaluate(tokens[-1], scope)
def parse(e: str):
tokens = []
s = ''
parenthesis = 0
for c in e:
if c == '(':
parenthesis += 1
elif c == ')':
parenthesis -= 1
if parenthesis == 0 and c == ' ':
tokens.append(s)
s = ''
else:
s += c
if len(s) > 0:
tokens.append(s)
return tokens
return evaluate(expression, {})