【栈】736. Lisp 语法解析

本文涉及知识点

LeetCode736. Lisp 语法解析

给你一个类似 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” 来表示,该表达式总是包含两个表达式 e1、e2 ,最终结果是 e1 表达式的值与 e2 表达式的值之 和 。
mult 表达式表示为 “(mult e1 e2)” ,其中 mult 总是以字符串 “mult” 表示,该表达式总是包含两个表达式 e1、e2,最终结果是 e1 表达式的值与 e2 表达式的值之 积 。
在该题目中,变量名以小写字符开始,之后跟随 0 个或多个小写字符或数字。为了方便,“add” ,“let” ,“mult” 会被定义为 “关键字” ,不会用作变量名。
最后,要说一下作用域的概念。计算变量名所对应的表达式时,在计算上下文中,首先检查最内层作用域(按括号计),然后按顺序依次检查外部作用域。测试用例中每一个表达式都是合法的。有关作用域的更多详细信息,请参阅示例。

示例 1:

输入:expression = “(let x 2 (mult x (let x 3 y 4 (add x y))))”
输出:14
解释:
计算表达式 (add x y), 在检查变量 x 值时,
在变量的上下文中由最内层作用域依次向外检查。
首先找到 x = 3, 所以此处的 x 值是 3 。
示例 2:

输入:expression = “(let x 3 x 2 x)”
输出:2
解释:let 语句中的赋值运算按顺序处理即可。
示例 3:

输入:expression = “(let x 1 y 2 x (add x y) (add x y))”
输出:5
解释:
第一个 (add x y) 计算结果是 3,并且将此值赋给了 x 。
第二个 (add x y) 计算结果是 3 + 2 = 5 。

提示:

1 <= expression.length <= 2000
exprssion 中不含前导和尾随空格
expressoin 中的不同部分(token)之间用单个空格进行分隔
答案和所有中间计算结果都符合 32-bit 整数范围
测试用例中的表达式均为合法的且最终结果为整数

包括 标识符(变量关键字) 常量 ( )
递归解析每个括号。unorder_map<string,stack> m_mVar 记录各变量的值。
一个括号从左到右解析,解析到变量入栈,本括号解析结束出栈。注意:不能先解析最内层括号,比如:(let x 2 add(x 1)) 先解析add会检测到未定义变量,而误认为是非法字符串。
Parse 函数大致流程:
一,如果有前置空格,忽略。忽略左括号。
二,解析命令名。
三,如果是加或乘法,读取两个值。并返回结果。
四,读取变量,如果失败则读值。
五,忽略空格后,如果是右括号。则计算返回值,并变量出栈。
六,忽略空格后,如果不是右括号。读取值,更新变量的值,并入栈。

IgronSpace :如果有空格,则忽略。
GetNum1:读取值,包括变量 常量 表达式。
ParseName:解析变量名,字母开始,后效字符可以是字母,也可以是数字。
ParseNum:解析数字和表达式。
注意:iPos指向下一个待处理的字符。

代码

核心代码

class Solution {
public:int evaluate(string expression) {m_exp = expression;int iPos = 0;return Parse(iPos);}int Parse(int& iPos) {auto tmp = m_exp.substr(iPos);while ((iPos < m_exp.length()) && ('(' != m_exp[iPos])) {iPos++;}iPos += 1;//跳过(和空格string strName = ParseName(iPos);iPos++;if ("mult" == strName) {int num1 = GetNum1(iPos);int num2 = GetNum1(++iPos);IgronSpace(iPos);iPos++;return num1 * num2;}if ("add" == strName) {int num1 = GetNum1(iPos);int num2 = GetNum1(++iPos);IgronSpace(iPos);iPos++;return num1 + num2;}assert("let" == strName);vector<string> vars;while (true) {auto iRet = 0;string strVarName = ParseName(iPos);if ("" != strVarName) {IgronSpace(iPos);					}else {iRet += GetNum1(iPos);IgronSpace(iPos);}if (')' == m_exp[iPos]) { if ("" != strVarName){iRet = m_mVar[strVarName].top();}for (auto var : vars) {//变量出栈m_mVar[var].pop();}iPos++;return  iRet;}vars.emplace_back(strVarName);const int cur = GetNum1(iPos);m_mVar[strVarName].emplace();m_mVar[strVarName].top() = cur;iPos++;}}void IgronSpace(int& iPos) {if((iPos < m_exp.length())&&(' ' == m_exp[iPos])){iPos++;};}int GetNum1(int& iPos) {string strName = ParseName(iPos);if ("" != strName) { return m_mVar[strName].top(); }return ParseNum(iPos);}string ParseName(int& iPos) {string strName;while ((isalpha(m_exp[iPos]))||(strName.size() && isalnum(m_exp[iPos]))) {strName += m_exp[iPos++];}return strName;}int ParseNum(int& iPos) {int num = 0;if ('(' == m_exp[iPos]) { return Parse(iPos); }int iSign = 1;if ('-' == m_exp[iPos]) {iSign = -1; iPos++;}while (isdigit(m_exp[iPos])) {num = num*10+ (m_exp[iPos]-'0');iPos++;}return iSign* num;}unordered_map<string, stack<int>> m_mVar;string m_exp;
};

单元测试

template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{Assert::AreEqual(t1 , t2);
}template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{Assert::AreEqual(v1.size(), v2.size());	for (int i = 0; i < v1.size(); i++){Assert::AreEqual(v1[i], v2[i]);}
}template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{sort(vv1.begin(), vv1.end());sort(vv2.begin(), vv2.end());Assert::AreEqual(vv1.size(), vv2.size());for (int i = 0; i < vv1.size(); i++){AssertEx(vv1[i], vv2[i]);}
}namespace UnitTest
{string expression;TEST_CLASS(UnitTest){public:TEST_METHOD(TestMethod0){expression = "(let x 2 (mult x (let x 3 y 4 (add x y))))";auto res = Solution().evaluate(expression);AssertEx(14,res);}TEST_METHOD(TestMethod1){expression = "(let x 3 x 2 x)";auto res = Solution().evaluate(expression);AssertEx(2, res);}TEST_METHOD(TestMethod2){expression = "(let x 1 y 2 x (add x y) (add x y))";auto res = Solution().evaluate(expression);AssertEx(5, res);}TEST_METHOD(TestMethod3){expression = "(let x 7 -12)";auto res = Solution().evaluate(expression);AssertEx(-12, res);}TEST_METHOD(TestMethod5){expression = "(let x 2 (add (let x 3 (let x 4 x)) x))";auto res = Solution().evaluate(expression);AssertEx(6, res);}TEST_METHOD(TestMethod6){expression = "(let x 2 (add (let x 3 4) x))";auto res = Solution().evaluate(expression);AssertEx(6, res);}TEST_METHOD(TestMethod7){expression = "(let x 2 (add 4 x))";auto res = Solution().evaluate(expression);AssertEx(6, res);}TEST_METHOD(TestMethod8){expression = "(let a1 3 b2 (add a1 1) b2)";auto res = Solution().evaluate(expression);AssertEx(4, res);}};
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
《喜缺全书算法册》以原理、正确性证明、总结为主。
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/22844.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电影推荐系统配置运行

电影推荐系统配置运行 代码地址项目介绍&#xff08;引自原文&#xff09; 环境创建新环境激活环境安装包创建管理员用户(可选)启动 代码地址 movie 项目介绍&#xff08;引自原文&#xff09; 本推荐系统采用的是分层模型设计思想&#xff0c;第一层为前端页面模型设计&…

C++ primer例子1实现

问题 代码 Sales_item.h #include<iostream> #include<string> class Sales_item {public:Sales_item(){};Sales_item(std::string insid, int num, double price);friend std::istream& operator>>(std::istream& is, Sales_item& item);frie…

springboot 图形验证码 前后端分离解决方案 easy-captcha

easy-captcha介绍 easy-captcha&#xff0c;提供了Java图形验证码&#xff0c;支持gif、中文、算术等类型&#xff0c;可用于Java Web、JavaSE等项目&#xff0c;是个很好用的工具库&#xff0c;文档比较完备。 用法 添加maven依赖 <!--图形验证码--><dependency&g…

支付系统-业务账单

target&#xff1a;离开柬埔寨倒计时-210day 前言 最近不知道该写什么了&#xff0c;很多东西要写起来非常耗时间&#xff0c;写作是真的不容易呀 我们的支付系统账单有两大类&#xff0c;一个是业务账单还有一个就是资金记录&#xff0c;都是引发资金流后的资金变动表现&…

高效数据处理的前沿:【C++】、【Redis】、【人工智能】与【大数据】的深度整合

目录 1.为什么选择 C 和 Redis&#xff1f; 2.人工智能与大数据的背景 1.大数据的挑战 2.人工智能的需求 3.C 与 Redis 的完美结合 1.安装 Redis 和 Redis C 客户端 2.连接 Redis 并进行数据操作 高级数据操作 列表操作 哈希操作 4.与大数据和人工智能结合 5.实际应…

机器学习18个核心算法模型

1. 线性回归&#xff08;Linear Regression&#xff09; 用于建立自变量&#xff08;特征&#xff09;和因变量&#xff08;目标&#xff09;之间的线性关系。 核心公式&#xff1a; 简单线性回归的公式为&#xff1a; , 其中 是预测值&#xff0c; 是截距&#xff0c; 是斜…

【C语言】结构体(及位段)

你好&#xff01;感谢支持孔乙己的新作&#xff0c;本文就结构体与大家分析我的思路。 希望能大佬们多多纠正及支持 &#xff01;&#xff01;&#xff01; 个人主页&#xff1a;爱摸鱼的孔乙己-CSDN博客 欢迎 互粉哦&#x1f648;&#x1f648;&#xff01; 目录 1. 声明结构…

解锁财富新篇章:消费增值模式引领未来消费趋势

你是否曾对日常消费感到一丝单调&#xff0c;认为它仅仅是一种物质上的交换&#xff0c;而非财富增长的途径&#xff1f;那么&#xff0c;让我们为你打开一扇全新的消费之门——消费增值模式。这不仅是一种全新的消费体验&#xff0c;更是一种让你的资金在消费过程中不断积累与…

百度地图API 教程使用 嵌套到vue3项目中使用,能够定位并且搜索地点名称位置,反向解析获取经度和维度

文章目录 目录 文章目录 流程 小结 概要安装流程技术细节小结 概要 注册百度地图成为开发者&#xff1a; 登录百度账号 注册成功开始下一步 百度地图API是百度提供的一组开发接口&#xff0c;用于在自己的应用程序中集成地图功能。通过百度地图API&#xff0c;您可以实现地图…

PS的抠图算法原理剖析 1

以这个抠tree为例子 在PS里&#xff0c;操作过程是让你开启R G B三个通道 分别看一下 哪一个的对比最明显 上面的图片 树叶肯定B最少 天空B富裕&#xff0c;所以对比最明显的就用B通道 然后使用一些奇怪的函数&#xff0c;把texture.bbb这张图片变成黑白&#xff0c;纯黑纯白 那…

mysql连接不上可能的原因:防火墙放行mysql的3306端口 全库复制:data目录替换即可 mysql查看版本

1.看本地localhost能否连接 2.在本地看IP能否连接 能说明本地正常 权限也够 都能的话&#xff0c;ip能否ping通 能就说明可能是防火墙原因了。关闭防火墙及杀毒试试。 我这里关防火墙就能访问了。 windows如何开启防火墙&#xff0c;又放行mysql的3306端口&#xff1f; 在 …

银行从业者心声:银行工作,是围城还是试炼场?

我的一个朋友&#xff0c;曾经对银行工作抱有美好的幻想&#xff0c;觉得那是一个光鲜亮丽、稳定无忧的职业。然而&#xff0c;当他真正踏入银行的大门&#xff0c;成为一名柜员后&#xff0c;才深刻体会到了其中的艰辛与不易。 他告诉我&#xff0c;银行的工作远非他想象中的…

十二、配置注解执行SQL

简化一下流程&#xff0c;主要可以分为下面几步&#xff1a; 1.解析配置&#xff0c;写入配置项 2.执行SQL 3.封装结果 通过注解配置SQL主要体现在解析部分&#xff0c;这部分要分别做解析XML还是配置注解的接口&#xff0c;拿到sql以后&#xff0c;select的处理和insert/upda…

创建 MFC DLL-使用DEF文件

本文仅供学习交流&#xff0c;严禁用于商业用途&#xff0c;如本文涉及侵权请及时联系本人将于及时删除 利用“MFC动态链接库”项目模板可以创建MFC DLL。DLL文件与可执行文件非常相似&#xff0c;不同点在于DLL包含有导出表(Export Table)。导出表包含DLL中每个导出函数的名字…

2024年5月份架构师考试案例真题完整版

案例分析&#xff1a; 今年的案例题 第一个必选题是 系统架构评估&#xff0c;文老师是押中了。 案例一&#xff1a;系统架构评估 1. 简述微服务架构 对比单体架构和微服务架构 微服务架构的优缺点。(7分) 答&#xff1a;微服务架构是一种分布式系统架构&#xff0c;将一个应用…

特征交叉系列:FM和深度神经网络的结合,DeepFM原理简述和实践

从FM&#xff0c;FFM到DeepFM 在上两节中介绍了FM和FFM 这两种算法是推荐算法中经典的特征交叉结构&#xff0c;FM将特征交叉分解到底层属性&#xff0c;通过底层属性的点乘来刻画特征交叉的计算&#xff0c;而FFM引入特征域的概念&#xff0c;对不同的特征对所引用的底层属性…

React中实现大模型的打字机效果

React 想实现一个打字机的效果&#xff0c;类似千问、Kimi 返回的效果。调用大模型时&#xff0c;模型的回答通常是流式输出的&#xff0c;如果等到模型所有的回答全部完成之后再展示给最终用户&#xff0c;交互效果不好&#xff0c;因为模型计算推理时间比较长。本文将采用原生…

SD3303A 大功率高亮度LED驱动芯片IC

一般描述 SD3303A是一款大功率高亮度LED驱动芯片,可以提供1A的电流驱动3W的LED。具有高效率&#xff0c;低功耗等特点&#xff0c;适用于电池供电的LED照明设备。 SD3303A具有开路保护和过温保护。 SD3303A需要使用两颗10uF(或者更大)的瓷片电容&#xff0c;来保…

AI大模型+产品经理:打造智能产品的黄金组合

前言 当我们谈论AI大模型与产品经理的结合&#xff0c;不仅仅是技术与创意的碰撞&#xff0c;更是对未来智能生活的期待。想象一下&#xff0c;当产品的灵魂被注入智能的血液&#xff0c;它们将成为我们生活中不可或缺的伙伴。 我们不仅仅是要探索AI大模型的深层技术&#xf…

深度缓冲技术在AI绘画中的魔法

随着人工智能技术的飞速发展&#xff0c;AI绘画已经成为艺术创作领域中的一个热门话题。从数字滤镜到复杂的图像生成算法&#xff0c;AI绘画正以前所未有的方式拓展着艺术的边界。在这个过程中&#xff0c;深度缓冲技术扮演了一个不可或缺的角色&#xff0c;它不仅提升了AI绘画…