同样是准备华为机考时做的一道题:
简单的 LISP 加减乘除语句解析并计算结果,四种运算符号为 add、sub、mul、div,分别为加减乘除。其中数字部分皆为整数。除法取整,除数为零输出 error。
例子:
(add 3 5 7) 结果为 15
(sub 1 9) 结果为 -8
(mul 0 9) 结果为 0
(div 8 3) 结果为 2
(div 8 0) 结果为 error
(add (sub (div 8 2) (mul 1 9)) 20) 结果为 15
#原题链接

确实正统的思路是用栈去实现啦,而且对特别复杂的公式而言效率会很高,但是不觉得只是一个简单的字符串处理没必要用那么复杂(主要是不想引java.util.Stack包,滑稽 )

废话就不多说了,主要实现思路是递归策略,每次递归都只计算最小的子串,例如:

(div (add (sub (div 8 2) (mul 1 9)) 20) (div 6 (add 1 1)))
=> div (add (sub (div 8 2) (mul 1 9)) 20) (div 6 (add 1 1))
=> (div (add (sub 4 9) 20) (div 6 2))
=> (div (add -5 20) 3)
=> (div 15 3)
=> 5

代码实现

package test;import java.math.BigDecimal;/*** 公式计算* * @author mona*/
public class Compute {public static void main(String[] args) {String s1 = "(add 3 5 7)";String s2 = "(sub 1 9 5)";String s3 = "(mul 2 9 1.5)";String s4 = "(div 20 2 3)";String s5 = "(div 8 0)";String s6 = "(add (sub (div 8 2) (mul 1 9)) 20)";String s7 = "div (add (sub (div 8 2) (mul 1 9)) 20) (div 6 (add 1 1))";System.out.println(getResult(s1));System.out.println(getResult(s2));System.out.println(getResult(s3));System.out.println(getResult(s4));System.out.println(getResult(s5));System.out.println(getResult(s6));System.out.println(getResult(s7));}/*** 计算方法(递归)* * @param s*            输入公式* @return 输出结果*/private static String getResult(String s) {try {// System.out.println("s => " + s);if (!s.startsWith("(")) {s = "(" + s + ")";// 兼容}String[] sa = s.split("\\(");for (int i = 0; i < sa.length; i++) {if (sa.length > 0) {// System.out.println("sa[" + i + "] => " + sa[i]);if (sa[i].indexOf(")") >= 0) {BigDecimal sa_r = null;String[] saa = null;String fun = "";if (sa[i].trim().startsWith("add")) {fun = "add";String sa_add = sa[i].trim().substring((sa[i].trim().indexOf(fun + " ") + 4), sa[i].trim().indexOf(")"));saa = sa_add.split(" ");sa_r = new BigDecimal(saa[0]);for (int j = 1; j < saa.length; j++) {sa_r = sa_r.add(new BigDecimal(sa_add.split(" ")[j]));}s = s.replace("(" + fun + " " + sa_add + ")", sa_r + "");} else if (sa[i].trim().startsWith("sub")) {fun = "sub";String sa_sub = sa[i].trim().substring((sa[i].trim().indexOf(fun + " ") + 4), sa[i].trim().indexOf(")"));saa = sa_sub.split(" ");sa_r = new BigDecimal(saa[0]);for (int j = 1; j < saa.length; j++) {sa_r = sa_r.subtract(new BigDecimal(sa_sub.split(" ")[j]));}s = s.replace("(" + fun + " " + sa_sub + ")", sa_r + "");} else if (sa[i].trim().startsWith("mul")) {fun = "mul";String sa_mul = sa[i].trim().substring((sa[i].trim().indexOf(fun + " ") + 4), sa[i].trim().indexOf(")"));saa = sa_mul.split(" ");sa_r = new BigDecimal(saa[0]);for (int j = 1; j < saa.length; j++) {sa_r = sa_r.multiply(new BigDecimal(sa_mul.split(" ")[j]));}s = s.replace("(" + fun + " " + sa_mul + ")", sa_r + "");// s = s.replace("(" + fun + " " + sa_mul + ")", sa_r.setScale(0, BigDecimal.ROUND_HALF_UP) + "");// 四舍五入} else if (sa[i].trim().startsWith("div")) {fun = "div";String sa_div = sa[i].trim().substring((sa[i].trim().indexOf(fun + " ") + 4),sa[i].trim().indexOf(")"));saa = sa_div.split(" ");sa_r = new BigDecimal(saa[0]);for (int j = 1; j < saa.length; j++) {if (new BigDecimal(sa_div.split(" ")[j]).equals(BigDecimal.ZERO)) {return "Error";// 除数不能为0} else {sa_r = sa_r.divide(new BigDecimal(sa_div.split(" ")[j]), BigDecimal.ROUND_HALF_UP);}}s = s.replace("(" + fun + " " + sa_div + ")", sa_r + "");}}}}if (s.indexOf("add") >= 0 || s.indexOf("sub") >= 0 || s.indexOf("mul") >= 0 || s.indexOf("div") >= 0) {return getResult(s);} else {return s;}} catch (Exception e) {return "Unknown Error";}}
}

当然了,不考虑特别复杂的计算的话,可以不用引BigDecimal包,我只是考虑到了一些特别麻烦的除法所以引入了而已。

之所以想用递归实现,不仅仅是因为觉得用栈麻烦,还为了方便异常字符处理,可能是我最近做前端太久了,潜意识总在想着异常输入的处理哈哈哈

解决问题的思路肯定不止一种,我只是提供了另一种解题思路而已,继续去做题了。

华为机考——LISP 加减乘除语句解析并计算结果相关推荐

  1. 2020-05-10 华为机考机试题目两题

    考试注意 牛客网考试 摄像头打开 屏幕录制 手机微信扫码保持屏幕常亮 可使用自己的 IDE 第一题 简单的 LISP 加减乘除语句解析并计算结果,四种运算符号为 add.sub.mul.div,分别为 ...

  2. 「解析」牛客网-华为机考企业真题 1-20

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  3. 「解析」牛客网-华为机考企业真题 41-60

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  4. 「解析」牛客网-华为机考企业真题 81-108

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  5. 「解析」牛客网-华为机考企业真题 21-40

    又是一年春招时,有幸收到华为自动驾驶算法岗,之前刷题不多,在此汇总下牛客网的真题,主要采用Python编写,个人觉得语言只是实现工具而已,并不是很关键,Python简洁易懂,更加适合算法工程师快速验证 ...

  6. 华为机考HJ13句子逆序C语言弱智解法

    华为机考HJ13句子逆序C语言弱智解法 句子逆序C语言低端解法,易于理解. 1.收数据老生常谈. 2.将句子全部逆序. 3.将单词正序. (这里有一个bug,最后一个词(原句子第一个词)总是收不到,所 ...

  7. 华为机考HJ7取近似值

    华为机考HJ7取近似值 只有小数点后一位,所以扩大十倍,让小数点后的数都为0. 然后强制转换成整型,不会影响精度. 强制转换原数的数据类型,无论原数据是什么,都只保留整数部分. 将扩大后的数对10求余 ...

  8. 华为机考HJ2计算字符个数

    华为机考HJ2计算字符个数 gets();每次收一行字符. getchar();每次收一个字符. 两个都存储后用第二个在第一个串中检索. 大小写的问题用大小写的ASCII码差值32解决. 暴力破解,没 ...

  9. 华为机考HJ1字符串最后一个单词的长度

    华为机考HJ1字符串最后一个单词的长度C语言解法 统计的是字符串最后一个单词的长度. 而不是单词的内容,所以单词的内容并不重要. 只需要用空格来做标志位即可. getchar():每次只收一个字符. ...

最新文章

  1. windows下给定多个openNi的Uri,匹配与uri对应的Uvc RGB设备
  2. Samba 系列(九):将 CentOS 7 桌面系统加入到 Samba4 AD 域环境中
  3. 任意进制转换简单理解
  4. 关于虚函数的应用(10个例子)
  5. python访问数据库oracle_python连接oracle数据库
  6. 怎样增加混凝土粘聚性_如何改善中低强度等级混凝土粘聚性? 这篇文章一定要看...
  7. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)
  8. kuka程序备份_那智机器人系统备份步骤
  9. [深度学习]理解RNN, GRU, LSTM 网络
  10. 【转】linx 设备名字来由 sd sr sg st
  11. 计数 APP android,SharedPreferences初学~个人备忘录以及对进入APP的次数进行计数
  12. RAISR-master:google图像新压缩技术RAISR的测试代码调试记录(Python实现,没接触过python的小白,内含pip install解决方案)
  13. 真正的轻量级WebService框架——使用JAX-WS(JWS)发布WebService
  14. 知识图谱基础入门(二)
  15. Xshell4 注册码 ,Xftp4 注册码
  16. 更改计算机时间格式,修改电脑日期时间显示格式
  17. ENSP与本地网络互连
  18. Altium未连接的网络DRC检查不出的问题
  19. 微商最低成本引流,学会这招日引精准粉1000+
  20. delphi xe 10.3 firemonkey stringdrig 插入,删除,添加

热门文章

  1. 实战SPECjvm2008
  2. 四年级计算机期末质量分析,四年级期末质量分析
  3. JS - 捕获打印窗口关闭事件
  4. 基于普中科技的单片机开发实验仪编写的数字表
  5. MySQL 性能优化总结
  6. Ubuntu的:有未能满足的依赖关系
  7. LaTeX 学习笔记 1 文件格式
  8. 关于setData 的报错
  9. php smtp 抄送,php带抄送和密件抄送的邮件发送方法_PHP教程
  10. BIN文件反汇编方法