Similar Problems
Similar Problems not available
Parse Lisp Expression - Leetcode Solution
Companies:
LeetCode: Parse Lisp Expression Leetcode Solution
Difficulty: Hard
Topics: string hash-table stack
The "Parse Lisp Expression" problem on LeetCode (https://leetcode.com/problems/parse-lisp-expression/) requires you to implement a Lisp interpreter that can evaluate expressions in a simplified version of the Lisp language.
The problem statement provides various examples of Lisp expressions that need to be evaluated, such as:
(add 1 2)
(mult 3 (add 2 3))
(let x 2 (mult x 5))
Your task is to implement a function evaluate
that takes a string parameter expression
representing a Lisp expression and returns its evaluation. You should assume that the input expression is well-formed.
To solve this problem, you can use recursion to evaluate the different types of expressions in the Lisp language. There are three types of Lisp expressions:
- Integer: an integer constant, such as "123"
- Symbol: a variable or operator, such as "add", "mult", or "x"
- List: a parenthesized expression that contains one or more sub-expressions
Here's a step-by-step approach to solving the problem:
- Define a function
parse
that takes a string representing a Lisp expression and returns a list of tokens. To do this, you can use regular expressions to split the input string into separate tokens. Here's an example implementation:
import re
def parse(expression: str) -> List[str]:
tokens = []
for token in re.findall(r'\(|\)|[^\s()]+', expression):
tokens.append(token)
return tokens
This function uses the regular expression r'\(|\)|[^\s()]+'
to split the input string into separate tokens, treating parentheses as separate tokens. For example, the expression "(add 1 2)" would be parsed into the list ["(", "add", "1", "2", ")"].
- Define a function
evaluate
that takes a list of tokens representing a Lisp expression and returns its evaluation. To do this, you can use recursion to evaluate the different types of expressions. Here's an example implementation:
def evaluate(tokens: List[str], env: Dict[str, int] = None) -> int:
if not tokens:
return 0
if env is None:
env = {}
token = tokens.pop(0)
if token == '(':
if tokens[0] == 'add':
tokens.pop(0)
arg1 = evaluate(tokens, env)
arg2 = evaluate(tokens, env)
return arg1 + arg2
elif tokens[0] == 'mult':
tokens.pop(0)
arg1 = evaluate(tokens, env)
arg2 = evaluate(tokens, env)
return arg1 * arg2
elif tokens[0] == 'let':
tokens.pop(0)
new_env = env.copy()
while tokens[0] != ')':
var = tokens.pop(0)
if tokens[0] == '(':
new_env[var] = evaluate(tokens, new_env)
else:
new_env[var] = int(tokens.pop(0))
tokens.pop(0) # pop final closing bracket
return evaluate(tokens, new_env)
else:
if token in env:
return env[token]
return int(token)
This function takes a list of tokens that represent a Lisp expression, as well as an optional environment dictionary that contains the current variable bindings. It returns an integer that represents the evaluation of the input expression.
The function begins by popping the first token from the token list and determining its type. If the token is an opening parenthesis, then it recursively evaluates the sub-expressions within the parentheses. If the sub-expression is a built-in function (i.e., "add" or "mult"), then it evaluates the arguments and applies the function. If the sub-expression is a "let" expression, then it creates a new environment dictionary with the variable bindings specified in the expression, and recursively evaluates the remaining expression with the new environment.
If the token is not an opening parenthesis, then it checks if it is a variable in the current environment dictionary. If it is, then it returns the value associated with the variable. Otherwise, it assumes that the token is an integer constant and returns its value.
- Define the main function
parse_lisp_expression
that takes a string parameterexpression
and returns its evaluation. Here's an example implementation:
from typing import List, Dict
def parse_lisp_expression(expression: str) -> int:
tokens = parse(expression)
return evaluate(tokens)
This function simply parses the input string into a list of tokens and then evaluates it using the evaluate
function.
- Test your implementation using the examples provided in the problem statement. For example:
assert parse_lisp_expression("(add 1 2)") == 3
assert parse_lisp_expression("(mult 3 (add 2 3))") == 15
assert parse_lisp_expression("(let x 2 (mult x 5))") == 10
assert parse_lisp_expression("(let x 2 (mult x (let x 3 y 4 (add x y))))") == 14
assert parse_lisp_expression("(let x 1 y 2 x (add x y) (add x y))") == 5
Overall, the Parse Lisp Expression
problem on LeetCode requires you to implement a Lisp interpreter that can evaluate expressions in a simplified version of the Lisp language. You can solve this problem by using recursion to evaluate the different types of Lisp expressions: integers, symbols, and lists. The parse
function tokenizes the input string, and the evaluate
function recursively evaluates the tokens using the current environment dictionary. With these functions, you can implement the parse_lisp_expression
function that parses and evaluates the input expression, and then test your implementation using the examples provided.
Parse Lisp Expression Solution Code
1