zoukankan      html  css  js  c++  java
  • [Swift]LeetCode736. Lisp 语法解析 | Parse Lisp Expression

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(shanqingyongzhi)
    ➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
    ➤GitHub地址:https://github.com/strengthen/LeetCode
    ➤原文地址: https://www.cnblogs.com/strengthen/p/10519773.html 
    ➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
    ➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

    You are given a string expressionrepresenting 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.

    给定一个类似 Lisp 语句的表达式 expression,求出其计算结果。

    表达式语法如下所示:

    • 表达式可以为整数,let 语法,add 语法,mult 语法。表达式的结果总是一个整数。
    • (整数可以是正整数、负整数、0)
    • let 语法表示为 (let v1 e1 v2 e2 ... vn en expr), 其中 let语法总是以字符串 "let"来表示,接下来会跟随一个或多个交替变量或表达式,也就是说,第一个变量 v1被分配为表达式 e1 的值,第二个变量 v2 被分配为表达式 e2 的值,以此类推;最终 let 语法的值为 expr表达式的值。
    • add语法表示为 (add e1 e2),其中 add 语法总是以字符串 "add"来表示,该语法总是有两个表达式e1e2, 该语法的最终结果是 e1表达式的值与 e2 表达式的值之和。
    • mult语法表示为 (mult e1 e2) ,其中 mult 语法总是以字符串"mult"表示, 该语法总是有两个表达式 e1e2,该语法的最终结果是 e1 表达式的值与 e2 表达式的值之积。
    • 在该题目中,变量的命名以小写字符开始,之后跟随0个或多个小写字符或数字。为了方便,"add","let","mult"会被定义为"关键字",不会在表达式的变量命名中出现。
    • 最后,要说一下范围的概念。在做计算时,需要注意优先级,在最内层(根据括号)的表达式的值应该先计算,然后依次计算外层的表达式。我们将保证每一个测试的表达式都是合法的。有关范围的更多详细信息,请参阅示例。 

    示例:

    输入: (add 1 2)
    输出: 3
    
    输入: (mult 3 (add 2 3))
    输出: 15
    
    输入: (let x 2 (mult x 5))
    输出: 10
    
    输入: (let x 2 (mult x (let x 3 y 4 (add x y))))
    输出: 14
    解释: 
    表达式 (add x y), 在获取 x 值时, 我们应当由最内层依次向外计算, 首先遇到了 x=3, 所以此处的 x 值是 3.
    
    输入: (let x 3 x 2 x)
    输出: 2
    解释: let 语句中的赋值运算按顺序处理即可
    
    输入: (let x 1 y 2 x (add x y) (add x y))
    输出: 5
    解释: 
    第一个 (add x y) 计算结果是 3,并且将此值赋给了 x 。
    第二个 (add x y) 计算结果就是 3+2 = 5 。
    
    输入: (let x 2 (add (let x 3 (let x 4 x)) x))
    输出: 6
    解释: 
    (let x 4 x) 中的 x 的作用范围仅在()之内。所以最终做加法操作时,x 的值是 2 。
    
    输入: (let a1 3 b2 (add a1 1) b2) 
    输出: 4
    解释: 
    变量命名时可以在第一个小写字母后跟随数字. 

    注意:

    • 我们给定的 expression 表达式都是格式化后的:表达式前后没有多余的空格,表达式的不同部分(关键字、变量、表达式)之间仅使用一个空格分割,并且在相邻括号之间也没有空格。我们给定的表达式均为合法的且最终结果为整数。
    • 我们给定的表达式长度最多为 2000 (表达式也不会为空,因为那不是一个合法的表达式)。
    • 最终的结果和中间的计算结果都将是一个 32 位整数。

    Runtime: 384 ms
    Memory Usage: 20.3 MB
     1 class Solution {
     2     func evaluate(_ expression: String) -> Int {        
     3         var m:[String:Int] = [String:Int]()
     4         return helper(expression, m)
     5     }
     6     
     7     func helper(_ str:String,_ m:[String:Int]) -> Int
     8     {
     9         var arr:[Character] = Array(str)
    10         var m = m
    11         if arr[0] == "-" || (arr[0] >= "0" && arr[0] <= "9")
    12         {
    13             return Int(str) ?? 0
    14         }
    15         else if arr[0] != "("
    16         {
    17             return m[str,default:0]
    18         }
    19         var s:String = str.subString(1, str.count - 2)
    20         var cur:Int = 0
    21         var cmd:String = parse(&s, &cur)
    22         if cmd == "let"
    23         {
    24             while (true) {
    25                 var str2 = parse(&s, &cur)
    26                 if cur > s.count 
    27                 {
    28                     return helper(str2, m)
    29                 }
    30                 var t:String = parse(&s, &cur)
    31                 m[str2] = helper(t, m)
    32             }
    33         }
    34         else if cmd == "add"
    35         {
    36             return helper(parse(&s, &cur), m) + helper(parse(&s, &cur), m)
    37         }
    38         else if cmd == "mult"
    39         {
    40             return helper(parse(&s, &cur), m) * helper(parse(&s, &cur), m)
    41         }    
    42         return 0
    43     }
    44     
    45     func parse(_ s:inout String,_ cur:inout Int) -> String
    46     {
    47         var end:Int = cur + 1
    48         var t:Int = cur
    49         var cnt:Int = 1
    50         if s[cur] == "("
    51         {
    52             while (cnt != 0)
    53             {
    54                 if s[end] == "("
    55                 {
    56                     cnt += 1
    57                 }
    58                 else if s[end] == ")"
    59                 {
    60                     cnt -= 1
    61                 }
    62                 end += 1
    63             }
    64             
    65         }
    66         else
    67         {
    68             while (end < s.count && s[end] != " ")
    69             {
    70                 end += 1            
    71             }
    72             
    73         }
    74         cur = end + 1
    75         return s.subString(t, end - t)
    76     }
    77 }
    78 
    79 extension String {
    80     //subscript函数可以检索数组中的值
    81     //直接按照索引方式截取指定索引的字符
    82     subscript (_ i: Int) -> Character {
    83         //读取字符
    84         get {return self[index(startIndex, offsetBy: i)]}
    85     }
    86     
    87     // 截取字符串:指定索引和字符数
    88     // - begin: 开始截取处索引
    89     // - count: 截取的字符数量
    90     func subString(_ begin:Int,_ count:Int) -> String {
    91         let start = self.index(self.startIndex, offsetBy: max(0, begin))
    92         let end = self.index(self.startIndex, offsetBy:  min(self.count, begin + count))
    93         return String(self[start..<end]) 
    94     }    
    95 }
  • 相关阅读:
    PhoneGap 的文件 api
    81-POJ-Wall(计算几何)
    12-凸包模板-计算几何
    80-计算几何-奶牛
    79-多边形的面积-计算几何
    78-直线相交-计算几何
    11-欧拉函数详解
    76-Relatives-欧拉函数
    29-中国剩余定理CRT
    2018.3.12 Leecode习题 给定一个整数数列,找出其中和为特定值的那两个数。
  • 原文地址:https://www.cnblogs.com/strengthen/p/10519773.html
Copyright © 2011-2022 走看看