Parse Lisp Expression
You are given a string expression representing a Lisp-like expression to return the integer value of.
The syntax for these expressions is given as follows.
- An expression is either an integer, a let-expression, an add-expression, a mult-expression, or an assigned variable. Expressions always evaluate to a single integer.
- (An integer could be positive or negative.)
- A let-expression takes the form
(let v1 e1 v2 e2 ... vn en expr), whereletis always the string"let", then there are 1 or more pairs of alternating variables and expressions, meaning that the first variablev1is assigned the value of the expressione1, the second variablev2is assigned the value of the expressione2, and so on sequentially; and then the value of this let-expression is the value of the expressionexpr.
- An add-expression takes the form
(add e1 e2)whereaddis always the string"add", there are always two expressionse1, e2, and this expression evaluates to the addition of the evaluation ofe1and the evaluation ofe2.
- A mult-expression takes the form
(mult e1 e2)wheremultis always the string"mult", there are always two expressionse1, e2, and this expression evaluates to the multiplication of the evaluation ofe1and the evaluation ofe2.
- For the purposes of this question, we will use a smaller subset of variable names. A variable starts with a lowercase letter, then zero or more lowercase letters or digits. Additionally for your convenience, the names "add", "let", or "mult" are protected and will never be used as variable names.
- Finally, there is the concept of scope. When an expression of a variable name is evaluated, within the context of that evaluation, the innermost scope (in terms of parentheses) is checked first for the value of that variable, and then outer scopes are checked sequentially. It is guaranteed that every expression is legal. Please see the examples for more details on scope.
Evaluation Examples:
Input: (add 1 2)
Output: 3 Input: (mult 3 (add 2 3))
Output: 15 Input: (let x 2 (mult x 5))
Output: 10 Input: (let x 2 (mult x (let x 3 y 4 (add x y))))
Output: 14
Explanation: In the expression (add x y), when checking for the value of the variable x,
we check from the innermost scope to the outermost in the context of the variable we are trying to evaluate.
Since x = 3 is found first, the value of x is 3. Input: (let x 3 x 2 x)
Output: 2
Explanation: Assignment in let statements is processed sequentially. Input: (let x 1 y 2 x (add x y) (add x y))
Output: 5
Explanation: The first (add x y) evaluates as 3, and is assigned to x.
The second (add x y) evaluates as 3+2 = 5. Input: (let x 2 (add (let x 3 (let x 4 x)) x))
Output: 6
Explanation: Even though (let x 4 x) has a deeper scope, it is outside the context
of the final x in the add-expression. That final x will equal 2. Input: (let a1 3 b2 (add a1 1) b2)
Output 4
Explanation: Variable names can contain digits after the first character.
Note:
- The given string
expressionis well formatted: There are no leading or trailing spaces, there is only a single space separating different components of the string, and no space between adjacent parentheses. The expression is guaranteed to be legal and evaluate to an integer. - The length of
expressionis at most 2000. (It is also non-empty, as that would not be a legal expression.) - The answer and all intermediate calculations of that answer are guaranteed to fit in a 32-bit integer.
因为input的结构比较固定,mult 和 add后面永远是接两个数或者表达式,或者一样一个,所以我们可以把input不断递归,使得最后input是一个数。这样就把问题解决了。
对于let,永远是多个pair+表达式,处理也是一样。
class Solution {
public int evaluate(String expression) {
return helper(expression, new HashMap<>());
}
private int helper(String expression, Map<String, Integer> map) {
if (isNumber(expression)) {
return Integer.parseInt(expression);
}
if (isVariable(expression)) {
return map.get(expression);
}
List<String> tokens = parse(expression);
if (tokens.get().equals("add")) {
return helper(tokens.get(), map) + helper(tokens.get(), map);
} else if (tokens.get().equals("mult")) {
return helper(tokens.get(), map) * helper(tokens.get(), map);
} else {
Map<String, Integer> newMap = new HashMap<>(map);
for (int i = ; i < tokens.size() - ; i += ) {
newMap.put(tokens.get(i), helper(tokens.get(i + ), newMap));
}
return helper(tokens.get(tokens.size() - ), newMap);
}
}
private boolean isNumber(String expression) {
char firstLetter = expression.charAt();
return firstLetter == '-' || firstLetter == '+' || firstLetter <= '' && firstLetter >= '';
}
private boolean isVariable(String expression) {
char firstLetter = expression.charAt();
return firstLetter <= 'z' && firstLetter >= 'a';
}
private List<String> parse(String exp) {
List<String> parts = new ArrayList<>();
exp = exp.substring(, exp.length() - );
int startIndex = ;
while (startIndex < exp.length()) {
int endIndex = next(exp, startIndex);
parts.add(exp.substring(startIndex, endIndex));
startIndex = endIndex + ;
}
return parts;
}
private int next(String expression, int startIndex) {
if (expression.charAt(startIndex) == '(') {
int count = ;
startIndex++;
while (startIndex < expression.length() && count > ) {
if (expression.charAt(startIndex) == '(') {
count++;
} else if (expression.charAt(startIndex) == ')') {
count--;
}
startIndex++;
}
} else {
while (startIndex < expression.length() && expression.charAt(startIndex) != ' ') {
startIndex++;
}
}
return startIndex;
}
}
如果问题里面没有let,代码可以简化为:
class Solution {
public int evaluate(String expression) {
if (isNumber(expression)) {
return Integer.parseInt(expression);
}
List<String> tokens = parse(expression);
if (tokens.get().equals("add")) {
return evaluate(tokens.get()) + evaluate(tokens.get());
} else {
return evaluate(tokens.get()) * evaluate(tokens.get());
}
}
private boolean isNumber(String expression) {
char firstLetter = expression.charAt();
return firstLetter == '-' || firstLetter == '+' || firstLetter <= '' && firstLetter >= '';
}
private List<String> parse(String exp) {
List<String> parts = new ArrayList<>();
exp = exp.substring(, exp.length() - );
int startIndex = ;
while (startIndex < exp.length()) {
int endIndex = next(exp, startIndex);
parts.add(exp.substring(startIndex, endIndex));
startIndex = endIndex + ;
}
return parts;
}
private int next(String expression, int index) {
if (expression.charAt(index) == '(') {
int count = ;
index++;
while (index < expression.length() && count > ) {
if (expression.charAt(index) == '(') {
count++;
} else if (expression.charAt(index) == ')') {
count--;
}
index++;
}
} else {
while (index < expression.length() && expression.charAt(index) != ' ') {
index++;
}
}
return index;
}
}
Parse Lisp Expression的更多相关文章
- [LeetCode] Parse Lisp Expression 解析Lisp表达式
You are given a string expression representing a Lisp-like expression to return the integer value of ...
- [Swift]LeetCode736. Lisp 语法解析 | Parse Lisp Expression
You are given a string expressionrepresenting a Lisp-like expression to return the integer value of. ...
- 736. Parse Lisp Expression
You are given a string expression representing a Lisp-like expression to return the integer value of ...
- 处理 javax.el.ELException: Failed to parse the expression 报错
在JSP的表达式语言中,使用了 <h3>是否新Session:${pageContext.session.new}</h3> 输出Session是否是新的,此时遇到了 j ...
- thymeleaf+layui加载页面渲染时TemplateProcessingException: Could not parse as expression
Caused by: org.attoparser.ParseException: Could not parse as expression: " {type: 'numbers'}, { ...
- org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:
- could not parse as expression: "/login" (template: "include/include" - line 32, col 42)
<li><a href="login.html" th:href="/login">登录</a></li> or ...
- layui表格数据渲染SpringBoot+Thymeleaf返回的数据时报错(Caused by: org.attoparser.ParseException: Could not parse as expression: ")
layui table渲染数据时报错(Caused by: org.attoparser.ParseException: Could not parse as expression: ") ...
- Tomcat报failed to parse the expression [${xxx}]异常(javax.el.ELException)的解决方法
Tomcat 7 'javax.el.ELException' 的解决方式tomcat 7对EL表达式的语法要求比较严格,例如"${owner.new}"因包含关键字new就会导致 ...
随机推荐
- 如何从word中直接复制图片到编辑器中
Chrome+IE默认支持粘贴剪切板中的图片,但是我要发布的文章存在word里面,图片多达数十张,我总不能一张一张复制吧?Chrome高版本提供了可以将单张图片转换在BASE64字符串的功能.但是无法 ...
- learning armbian steps(6) ----- armbian 源码分析(一)
为了深入学习armbian,前面已经学习了如何手动构建arm ubuntu rootfs. 由于armbian官方的文档比较的匮乏,所以最终还是决定通过其编译的过程来深入地学习. 为了快速度深入地学习 ...
- java中的变量和数据类型
变量和javascript的变量含义一样 在Java中,变量分为两种:基本类型的变量和引用类型的变量.(javascript中同样是这样的) 基本数据类型 基本数据类型是CPU可以直接进行运算的类型. ...
- HashMap简单介绍
哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表. 一.什么是哈希表 在讨论哈希表之 ...
- legend3---12、DB::table('user_questions')和UserQuestion查询的结果的格式不一样
legend3---12.DB::table('user_questions')和UserQuestion查询的结果的格式不一样 一.总结 一句话总结: 推荐使用模型查找的方式,可以直接数组方式访问: ...
- Java-CAS 与原子类
CAS(Compare and Swap),即比较并替换,实现并发算法时常用到的一种技术. CAS 的思想很简单:三个参数,一个当前内存值 V.旧的预期值 A.即将更新的值 B,当且仅当预期值 A 和 ...
- mysql授权指定ip远程登录
use user //更新用户表: UPDATE `user` SET `Host` = '175.6.6.230' where `Host` = '175.6.6.230'; //授权用户表: GR ...
- 【批处理】ren命令_批量重命名文件
[ren命令] 说明:ren是“rename(重命名)”的简写: 命令:REN [Drive:][path] <old filename> <new filename> 解释: ...
- handler四元素
Looper 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列). 我们知道一个线程是一段可执行的代码,当可执行代码执行完成后,线程生命周期便会终止,线程就 ...
- pytest+allure展示环境信息
allure展示环境信息 要将信息添加到Environment小部件,只需在生成报告之前在目录中创建environment.properties(或environment.xml)文件allure-r ...