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), where let is always the string "let", then there are 1 or more pairs of alternating variables and expressions, meaning that the first variable v1 is assigned the value of the expression e1, the second variable v2 is assigned the value of the expression e2, and so on sequentially; and then the value of this let-expression is the value of the expression expr.
  • An add-expression takes the form (add e1 e2)where add is always the string "add", there are always two expressions e1, e2, and this expression evaluates to the addition of the evaluation of e1 and the evaluation of e2.
  • A mult-expression takes the form (mult e1 e2)where mult is always the string "mult", there are always two expressions e1, e2, and this expression evaluates to the multiplication of the evaluation of e1and the evaluation of e2.
  • 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 expression is 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 expression is 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的更多相关文章

  1. [LeetCode] Parse Lisp Expression 解析Lisp表达式

    You are given a string expression representing a Lisp-like expression to return the integer value of ...

  2. [Swift]LeetCode736. Lisp 语法解析 | Parse Lisp Expression

    You are given a string expressionrepresenting a Lisp-like expression to return the integer value of. ...

  3. 736. Parse Lisp Expression

    You are given a string expression representing a Lisp-like expression to return the integer value of ...

  4. 处理 javax.el.ELException: Failed to parse the expression 报错

    在JSP的表达式语言中,使用了  <h3>是否新Session:${pageContext.session.new}</h3>  输出Session是否是新的,此时遇到了  j ...

  5. thymeleaf+layui加载页面渲染时TemplateProcessingException: Could not parse as expression

    Caused by: org.attoparser.ParseException: Could not parse as expression: " {type: 'numbers'}, { ...

  6. org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:

    org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression:

  7. could not parse as expression: "/login" (template: "include/include" - line 32, col 42)

    <li><a href="login.html" th:href="/login">登录</a></li> or ...

  8. 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: ") ...

  9. Tomcat报failed to parse the expression [${xxx}]异常(javax.el.ELException)的解决方法

    Tomcat 7 'javax.el.ELException' 的解决方式tomcat 7对EL表达式的语法要求比较严格,例如"${owner.new}"因包含关键字new就会导致 ...

随机推荐

  1. Luogu P1450 [HAOI2008]硬币购物 背包+容斥原理

    考虑如果没有个数的限制,那么就是一个完全背包,所以先跑一个完全背包,求出没有个数限制的方案数即可. 因为有个数的限制,所以容斥一下:没有1个超过限制的方案=至少0个超过限制-至少1个超过限制+至少2个 ...

  2. linux终端相关概念解释及描述

    基本概念: 1. tty(终端设备的统称): tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息的东西,后来这东西被 ...

  3. GC 老年代 新生代

    参考资料: http://blog.csdn.net/flamezyg/article/details/44673951 http://www.blogjava.net/ldwblog/archive ...

  4. node中的stream(流)内置模块

    stream是Node.js提供的又一个仅在服务区端可用的模块,目的是支持“流”这种数据结构. 什么是流?流是一种抽象的数据结构.想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地 ...

  5. 测试Promise与Async/await的基本使用

    想在项目中用, 发现自己不是很熟 promise基本使用 基本使用-思路 new Promise()返回了一个状态机 一个完全无法被外界影响的状态机 构造函数, 传入一个函数, 两个参数, 分别是re ...

  6. From 7.29 To 8.4

    From 7.29 To 8.4 大纲 英语按时背 做点思维题 可能还有时间学点东西, 这周我也不知道应该干什么 7.29 上午考试, 终于有一回不是自闭的考试了 题目比较简单, 就不说了 7.30 ...

  7. hadoop-job(mapReducer计算单词出现的个数)

    1.============map=============== package com.it18zhang.hadoop.mr; import org.apache.hadoop.io.IntWri ...

  8. Linux | linux的那些常见目录

    1. bin目录 binary(二进制的):许多"指令"对应的可"执行程序文件"目录 2. sbin目录 说明:super binary 超级的 二进制 许多& ...

  9. C++ STL——map和multimap

    目录 一 map和multimap 注:原创不易,转载请务必注明原作者和出处,感谢支持! 一 map和multimap map相对于set的区别:map具有键值和实值,所有元素根据键值自动排序.pai ...

  10. vscode如何右键选择浏览器运行html文件

    我们利用Vscode软件编写html的时候,一般都想右键选择html文件,然后直接选择浏览器运行,但是默认是没有的: 下面鄙人给大家分享一下如何设置. 这里你会发现有好多类似的插件,你自己选择一个喜欢 ...