【刷题】华为笔试题---仿LISP算法(Python实现)
最近做了一道华为的机试题,搜索之后没有找到Python实现,因此根据C++的代码实现了Python版,测试了题目描述的样例是都通过了。
1.题目描述:
-
LISP语言唯一的语法就是括号要配对。
形如 (OP P1 P2 …),括号内元素由单个空格分割。
其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型
注意:参数 P1, P2 也有可能是另外一个嵌套的 (OP P1 P2 …)
当前OP类型为add/sub/mul/div(全小写),分别代表整数的加减乘除法。简单起见,所以OP参数个数为2 -
举例:
输入:(mul 3 -7)输出:-21
输入:(add 1 2) 输出:3
输入:(sub (mul 2 4) (div 9 3)) 输出 :5
输入:(div 1 0) 输出:error
2.分析:
首先确定使用递归的思路来解题,然后明确递归函数的功能。设递归函数为solve_lisp(lisp_str)
,这个函数的功能是解析lisp样式的字符串,然后返回计算的结果(int型)。假设lisp_str的形式为'(op (sub_str1) (sub_str2)...(sub_strn))',那么solve_lisp()
可以分以下5步实现:
- 有括号去括号;
- 获得操作符
op
,创建list
用于保存后面解析的sub_str的值; - 解析sub_str中的
(
、)
和数字
; - 根据操作符
op
和list
中的数字,计算最后的结果; - 处理error情况、处理负号。
3.实现:
def solve_lisp(lisp_str):
'''
解析lisp字符串,返回一个数值
'''
# 去掉空格
lisp_str = lisp_str.strip()
# 去掉括号
if lisp_str[0] == '(':
lisp_str = lisp_str[1:]
if lisp_str[-1] == ')':
lisp_str = lisp_str[:-1]
# 解析操作符
op = lisp_str[:3]
lisp_str = lisp_str[3:]
# 保存解析出来的数值
nums = []
# 解析括号内的字符串
i = 0
while i < len(lisp_str):
c = lisp_str[i]
if c.isdigit() or c == '-' or c == '+':
j = i
while j < len(lisp_str) and (lisp_str[j].isdigit() or lisp_str[j] == '-' or lisp_str[j] == '+'): # or 需要加括号,否则越界
j += 1
nums.append(int(lisp_str[i:j]))
i = j
elif c == '(':
j = i
cnt = 0
while j < len(lisp_str):
if lisp_str[j] == '(':
cnt += 1
elif lisp_str[j] == ')':
cnt -= 1
j += 1
if cnt == 0:
break
nums.append(solve_lisp(lisp_str[i:j]))
i = j
else:
i += 1
# 计算数值
# print(op, nums)
if op == 'mul':
cum = 1
for num in nums:
cum *= num
return cum
elif op == 'add':
return sum(nums)
elif op == 'div':
return int(nums[0] / nums[1])
elif op == 'sub':
return nums[0] - nums[1]
def solve(lisp_str):
try:
print(solve_lisp(lisp_str))
except Exception:
print('error')
while True:
solve(input())