1. 题目描述
-
要求:输入一组复杂指标计算公式以及公式中包含的基础指标的值,计算出指定指标的值并返回
- 复杂指标公式示例
- [123654] = [6598]/[6665] *{100}
- 其中 [] 中的内容为复杂指标,{} 中的为整型常量
- 复杂指标公式示例
-
输入描述
输入一个字符串使用分号分隔符为如下3部分
- 一组指标的计算公式,公式之间使用逗号 , 分隔
- 所有基础指标的值,指标值使用如 [1254]=3 来表示,指标之间用 , 分隔
- 需要计算的指标ID
注意
- 公式中只会出现 “+”, “-”, “*", "/", "[指标ID]”, "{整数}" 六种格式
- 复杂指标公式中可能含有复杂指标
- 所有数据均为整数,且公式中运算结果包括除法也保证结果为整数
-
输入输出示例
-
输入
[1234]=[12]+[34]*{50},[12]=[1]+[2]/{2};[1]=10,[2]=20,[34]=50;[1234]
-
输出
2520
-
2. 代码部分
废话少说,先上 python 3代码:
PRIORITY = {"+": 1, "-": 1, "*": 2, "/": 2} # 运算符及其优先级
def calc(var, all_vars):
"""迭代计算给定变量的值"""
if type(all_vars[var]) is int:
return all_vars[var] # 字典中的值为整型,说明计算完成,直接返回值
formula = list(all_vars[var]) # 公式转换为列表,方便从左到右遍历
numbers = list() # 数字栈
operators = list() # 符号栈
number = '' # 公式中与数字相关的量
while True:
if not formula:
# 到公式未尾,如果数字不为空,则压入最后一个变量对应的整数
if number:
numbers.append(calc(number, all_vars))
# 清空符号栈
while operators:
numbers.append(calc_two_number(numbers, operators)) # 计算结果要压入数字栈
all_vars[var] = numbers[-1] # 将字典中的公式更新为整型值
return numbers.pop()
ch = formula.pop(0) # 从左向右遍历
if "0" <= ch <= "9":
number += ch # 拼接数字
if formula:
# 判断当前数字的拼接是否到头
if formula[0] == "}":
# 说明读入的数字为整形常量
formula.pop(0)
numbers.append(int(number))
number = ""
elif formula[0] in PRIORITY.keys():
numbers.append(calc(number, all_vars)) # 递归运算
number = ""
elif ch in PRIORITY.keys():
if operators and PRIORITY[ch] <= PRIORITY[operators[-1]]:
numbers.append(calc_two_number(numbers, operators))
operators.append(ch)
def calc_two_number(numbers, operators):
"""计算两个数的值"""
right = numbers.pop() # 先弹左值
left = numbers.pop() # 再弹右值
oper = operators.pop()
if oper == "+":
return left + right
elif oper == "-":
return left - right
elif oper == "*":
return left * right
elif oper == "/":
return left // right # 定要防止出现小数
def handle_input_str(input_str):
"""处理输入的字符串,提取逗号分隔的 3 个部分的内容"""
input_list = input_str.replace('[', '').replace(']', '').split(';') # [ ] 于计算无实际作用,去掉
res_var = input_list[2]
all_vars = dict() # 所有 [] 中对应变量组成的字典
# 根据 = 号分出左右值,左值作为字典的键,右值作为字典的值
second_part = input_list[1].split(',')
for item in second_part:
left_right = item.split('=')
all_vars[left_right[0]] = int(left_right[1]) # 储存为整型值
first_part = input_list[0].split(',')
for item in first_part:
left_right = item.split('=')
all_vars[left_right[0]] = left_right[1] # 将公式储存入字典中
return res_var, all_vars
def main(input_str):
if not input_str:
input_str = input()
res_var, all_vars = handle_input_str(input_str)
print(calc(res_var, all_vars))
if __name__ == "__main__":
main('[1234]=[12]+[34]*{50},[12]=[1]+[2]/{2};[1]=10,[2]=20,[34]=50;[1234]')
3. 代码解释
主要用到的数据结构为栈和字典
handle_input_str
函数主要是对输入的字符串进行处理,将复杂指标储存为字典的键,其对应的值可能为实际结果(计算值),也可能是复杂公式。其中,由于 [] 在计算中基本不起作用,故从公式中去掉
calc
函数则用用来计算给定的复杂指标,如果字典 all_vars
中复杂指标对应的值已为整型,则直接返回其值即可。否则需要计算复杂公式
复杂公式的计算与常规的字符串的四则运算相同,基础的数据结构是采用一个符号栈和一个数字栈,代码中直接使用 python 内建的 list
类型来起到栈的作用。与四则运算不同的是,需要判断读取到的数字是复杂指标还是常量,如果是复杂指标,则迭代调用 calc
函数进行计算。
calc
函数计算得到最终值后,需要更新 all_vars
中的值,以避免重复计算
calc_two_numbers
函数中的除法,要用 // 整除符号