736. Parse Lisp Expression

LeetCode hard оригинал: C# #array #csharp #hard #hash-table #leetcode #recursion #string

Нам дан массив asteroids, состоящий из целых чисел, представляющих астероиды в ряд. Для каждого астероида абсолютное значение обозначает его размер, а знак - направление движения (положительное - вправо, отрицательное - влево). Каждый астероид движется с одинаковой скоростью. Определите состояние астероидов после всех столкновений. Если два астероида столкнутся, меньший из них взорвется. Если оба одинакового размера, то взорвутся оба. Два астероида, движущиеся в одном направлении, никогда не встретятся.

Пример:

Input: expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))"

Output: 14

C# решение

сопоставлено/оригинал
public class Solution {
    public int Evaluate(string expression) {
        return Evaluate(expression, new Dictionary<string, int>());
    }
    
    private int Evaluate(string expression, Dictionary<string, int> env) {
        if (expression[0] != '(') {
            return int.TryParse(expression, out var result) ? result : env[expression];
        }
        
        var tokens = Tokenize(expression);
        if (tokens[0] == "let") {
            for (int i = 1; i < tokens.Count - 2; i += 2) {
                env[tokens[i]] = Evaluate(tokens[i + 1], env);
            }
            return Evaluate(tokens[^1], env);
        } else if (tokens[0] == "add") {
            return Evaluate(tokens[1], env) + Evaluate(tokens[2], env);
        } else if (tokens[0] == "mult") {
            return Evaluate(tokens[1], env) * Evaluate(tokens[2], env);
        }
        return 0;
    }
    
    private List<string> Tokenize(string expression) {
        var tokens = new List<string>();
        var token = string.Empty;
        int parens = 0;
        foreach (var c in expression) {
            if (c == '(') {
                parens++;
                if (parens == 1) continue;
            } else if (c == ')') {
                parens--;
                if (parens == 0) {
                    tokens.AddRange(Tokenize(token));
                    token = string.Empty;
                    continue;
                }
            } else if (c == ' ' && parens == 1) {
                if (!string.IsNullOrEmpty(token)) {
                    tokens.Add(token);
                    token = string.Empty;
                }
                continue;
            }
            token += c;
        }
        if (!string.IsNullOrEmpty(token)) {
            tokens.Add(token);
        }
        return tokens;
    }
}

C++ решение

auto-draft, проверить перед отправкой
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    public int Evaluate(string expression) {
        return Evaluate(expression, new unordered_map<string, int>());
    }
    
    private int Evaluate(string expression, unordered_map<string, int> env) {
        if (expression[0] != '(') {
            return int.TryParse(expression, out var result) ? result : env[expression];
        }
        
        var tokens = Tokenize(expression);
        if (tokens[0] == "let") {
            for (int i = 1; i < tokens.size() - 2; i += 2) {
                env[tokens[i]] = Evaluate(tokens[i + 1], env);
            }
            return Evaluate(tokens[^1], env);
        } else if (tokens[0] == "add") {
            return Evaluate(tokens[1], env) + Evaluate(tokens[2], env);
        } else if (tokens[0] == "mult") {
            return Evaluate(tokens[1], env) * Evaluate(tokens[2], env);
        }
        return 0;
    }
    
    private List<string> Tokenize(string expression) {
        var tokens = new List<string>();
        var token = string.Empty;
        int parens = 0;
        foreach (var c in expression) {
            if (c == '(') {
                parens++;
                if (parens == 1) continue;
            } else if (c == ')') {
                parens--;
                if (parens == 0) {
                    tokens.AddRange(Tokenize(token));
                    token = string.Empty;
                    continue;
                }
            } else if (c == ' ' && parens == 1) {
                if (!string.IsNullOrEmpty(token)) {
                    tokens.push_back(token);
                    token = string.Empty;
                }
                continue;
            }
            token += c;
        }
        if (!string.IsNullOrEmpty(token)) {
            tokens.push_back(token);
        }
        return tokens;
    }
}

Java решение

сопоставлено/оригинал
import java.util.*;

public class Solution {
    public int evaluate(String expression) {
        return evaluate(expression, new HashMap<>());
    }
    
    private int evaluate(String expression, Map<String, Integer> env) {
        if (!expression.startsWith("(")) {
            if (Character.isDigit(expression.charAt(0)) || expression.charAt(0) == '-') {
                return Integer.parseInt(expression);
            }
            return env.get(expression);
        }
        
        List<String> tokens = tokenize(expression);
        if (tokens.get(0).equals("let")) {
            for (int i = 1; i < tokens.size() - 2; i += 2) {
                env.put(tokens.get(i), evaluate(tokens.get(i + 1), env));
            }
            return evaluate(tokens.get(tokens.size() - 1), env);
        } else if (tokens.get(0).equals("add")) {
            return evaluate(tokens.get(1), env) + evaluate(tokens.get(2), env);
        } else if (tokens.get(0).equals("mult")) {
            return evaluate(tokens.get(1), env) * evaluate(tokens.get(2), env);
        }
        return 0;
    }
    
    private List<String> tokenize(String expression) {
        List<String> tokens = new ArrayList<>();
        StringBuilder token = new StringBuilder();
        int parens = 0;
        for (char c : expression.toCharArray()) {
            if (c == '(') {
                parens++;
                if (parens == 1) continue;
            } else if (c == ')') {
                parens--;
                if (parens == 0) {
                    tokens.addAll(tokenize(token.toString()));
                    token = new StringBuilder();
                    continue;
                }
            } else if (c == ' ' && parens == 1) {
                if (token.length() > 0) {
                    tokens.add(token.toString());
                    token = new StringBuilder();
                }
                continue;
            }
            token.append(c);
        }
        if (token.length() > 0) {
            tokens.add(token.toString());
        }
        return tokens;
    }
}

JavaScript решение

сопоставлено/оригинал
class Solution {
    evaluate(expression) {
        const evaluate = (expression, env) => {
            if (!expression.startsWith('(')) {
                if (isNaN(expression)) {
                    return env[expression];
                }
                return parseInt(expression);
            }
            
            const tokens = tokenize(expression);
            if (tokens[0] === 'let') {
                for (let i = 1; i < tokens.length - 2; i += 2) {
                    env[tokens[i]] = evaluate(tokens[i + 1], env);
                }
                return evaluate(tokens[tokens.length - 1], env);
            } else if (tokens[0] === 'add') {
                return evaluate(tokens[1], env) + evaluate(tokens[2], env);
            } else if (tokens[0] === 'mult') {
                return evaluate(tokens[1], env) * evaluate(tokens[2], env);
            }
        };
        
        const tokenize = (expression) => {
            let tokens = [];
            let token = '';
            let parens = 0;
            for (let char of expression) {
                if (char === '(') {
                    parens++;
                    if (parens === 1) {
                        continue;
                    }
                } else if (char === ')') {
                    parens--;
                    if (parens === 0) {
                        tokens.push(tokenize(token));
                        token = '';
                        continue;
                    }
                } else if (char === ' ' && parens === 1) {
                    if (token) {
                        tokens.push(token);
                        token = '';
                    }
                    continue;
                }
                token += char;
            }
            if (token) {
                tokens.push(token);
            }
            return tokens;
        };
        
        return evaluate(expression, {});
    }
}

Python решение

сопоставлено/оригинал
class Solution:
    def evaluate(self, expression: str) -> int:
        def evaluate(expression, env):
            if expression[0] != '(':
                if expression[0].isalpha():
                    return env[expression]
                return int(expression)
            
            tokens = tokenize(expression)
            if tokens[0] == 'let':
                for i in range(1, len(tokens) - 2, 2):
                    env[tokens[i]] = evaluate(tokens[i + 1], env)
                return evaluate(tokens[-1], env)
            elif tokens[0] == 'add':
                return evaluate(tokens[1], env) + evaluate(tokens[2], env)
            elif tokens[0] == 'mult':
                return evaluate(tokens[1], env) * evaluate(tokens[2], env)
        
        def tokenize(expression):
            tokens, token, parens = [], '', 0
            for char in expression:
                if char == '(':
                    parens += 1
                    if parens == 1:
                        continue
                elif char == ')':
                    parens -= 1
                    if parens == 0:
                        tokens.append(tokenize(token))
                        token = ''
                        continue
                elif char == ' ' and parens == 1:
                    if token:
                        tokens.append(token)
                        token = ''
                    continue
                token += char
            if token:
                tokens.append(token)
            return tokens
        
        return evaluate(expression, {})

Go решение

сопоставлено/оригинал
package main

import (
    "strconv"
    "strings"
)

func evaluate(expression string) int {
    return evaluateExpression(expression, map[string]int{})
}

func evaluateExpression(expression string, env map[string]int) int {
    if expression[0] != '(' {
        if val, err := strconv.Atoi(expression); err == nil {
            return val
        }
        return env[expression]
    }

    tokens := tokenize(expression)
    if tokens[0] == "let" {
        for i := 1; i < len(tokens)-2; i += 2 {
            env[tokens[i]] = evaluateExpression(tokens[i+1], env)
        }
        return evaluateExpression(tokens[len(tokens)-1], env)
    } else if tokens[0] == "add" {
        return evaluateExpression(tokens[1], env) + evaluateExpression(tokens[2], env)
    } else if tokens[0] == "mult" {
        return evaluateExpression(tokens[1], env) * evaluateExpression(tokens[2], env)
    }
    return 0
}

func tokenize(expression string) []string {
    tokens := []string{}
    token := ""
    parens := 0
    for _, char := range expression {
        switch char {
        case '(':
            parens++
            if parens == 1 {
                continue
            }
        case ')':
            parens--
            if parens == 0 {
                tokens = append(tokens, tokenize(token)...)
                token = ""
                continue
            }
        case ' ':
            if parens == 1 {
                if token != "" {
                    tokens = append(tokens, token)
                    token = ""
                }
                continue
            }
        }
        token += string(char)
    }
    if token != "" {
        tokens = append(tokens, token)
    }
    return tokens
}

Algorithm

Определите функцию для оценки выражений.

Используйте рекурсивный подход для обработки различных типов выражений (let, add, mult, и переменных).

Используйте словарь для отслеживания значений переменных с учетом области видимости.

😎

Вакансии для этой задачи

Показаны активные вакансии с пересечением по тегам задачи.

Все вакансии
Активных вакансий пока нет.