测试用例来源
被某汤姓老师无情霸占写代码时间的我一拖再拖终于更了这道题
画上了一个圆满的省略号
0分思路
其实我一开始写的版本思路贼他妈清奇
用Python做过那道二十四点的同学应该都知道
Python有个非常牛x的函数eval
可以对str型的数学表达式求值
于是看到这种判断表达式是否相等的题我的心情异常激动
那怎么把化学方程式转化成数学表达式呢
相对原子质量还记得吗
可以把每个化学元素替换成唯一的一个数字
然后凑一下表达式的形式
最后用eval
当然要注意不能真的用相对原子质量
假如H的质量是1,He的质量是2
那么H2=He
的结果就是Y了
显然有问题
聪明如我
立马上某度搜了质数表和元素周期表
自己在代码里写了个dict建立了元素到质数的映射
测试用例都过了没问题
但是天杀的CCF评测肯定用了不是正常化学元素的字母比如Aa Bb啥的
所以光荣的0分了
50分思路
然后乖乖地改为统计两边元素和了
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH
以此方程式为例
先用split('=')
分为左右两部分
然后用split('+')
把各个化学式分开
以最繁的化学式4Na(Au(CN)2)
为例
用一个list记录其中的所有元素(可重复)
忽然想到用dict可能更好
比如 {‘H’: 2, ‘Au’: 5}
首先提取它的系数4
然后判断第一个是何种元素,或者是左括号
如果是元素则提取它的下标,向list中添加这个元素x次,x即为它的下标
如果是括号则递归调用自己,将括号内的字符串(子化学式)作为参数再传给此方法
最后返回化学式系数 * 元素list
即此化学式的所有元素
思路没问题
然而递归超时了
比如测试用例
(((((((((((((A)13)12)11)10)9)8)7)6)5)4)3)2)1=1(2(3(4(5(6(7(8(9(10(11(12(13(A)))))))))))))
直接给我电脑跑死机了
最后只拿了50分
def get_match_paren_index(left_paren_index, my_str):
# 传入当前左括号的索引,和整个str,返回与其匹配的右括号的索引
my_stack = []
# 栈
if my_str[left_paren_index] != '(':
return None
else:
for i in range(left_paren_index, len(my_str), 1):
if my_str[i] == '(':
# 左括号则将其索引压栈
my_stack.append(i)
elif my_str[i] == ')':
# 右括号则弹栈
my_stack.pop()
if not my_stack:
# 如果弹栈后栈空则返回右括号的索引
return i
def find_subscription(chemic_formula, element_start, element_type):
# 输入不含系数的化学式,元素(双, 单, 左括号)的起始位置,元素的类型(doub, sing, lepa)
# 返回 其下标, 元素的结束位置, 下标的结束位置
step = 0
# 跳过几个字母开始提取下标
if element_type == "doub":
step = 2
elif element_type == "sing":
step = 1
elif element_type == "lepa":
step = get_match_paren_index(element_start, chemic_formula) - element_start + 1
# 找到与之匹配的右括号的索引,跳过step个长度开始提取下标
subscription = '1'
# 下标
subscription_end = element_start + step
# 默认下标为1时的结束位置(不含)
if chemic_formula[element_start + step].isdigit():
# 如果有数字则提取下标,否则下标为1
for j in range(element_start + step, len(chemic_formula), 1):
if not chemic_formula[j].isdigit():
# 找到其后的第一个非数字
subscription = chemic_formula[element_start + step: j]
# 提取下标
subscription_end = j
# 改变下标结束的位置
break
# 找到符合条件的j则break
return subscription, step, subscription_end
def rtn_result(chemic_formula):
# 输入化学式如25Ag35NO3NO2(34Ba(OH)2)5TiO4
print('* begin in: ', chemic_formula)
all_elements = []
# 存放所有元素到列表all_elements
formula_coefficient = 1
# 化学式系数
chemic_formula += '.'
# 防止下标越界
if chemic_formula[0].isdigit():
# 如果字符串首是数字则提取系数,否则系数为1
for i in range(len(chemic_formula)):
if not chemic_formula[i].isdigit():
formula_coefficient = chemic_formula[0: i]
# 提取化学式的系数
chemic_formula = chemic_formula[i: -1] + chemic_formula[-1]
# 将化学式去掉系数
break
i = 0
while True:
element = []
element_type = ""
if chemic_formula[i].isupper() and chemic_formula[i+1].islower():
# 如果是双字母元素
element.append(chemic_formula[i: i+2])
element_type = "doub"
elif chemic_formula[i].isupper() and not chemic_formula[i+1].islower():
# 单字母元素
element.append(chemic_formula[i: i+1])
element_type = "sing"
elif chemic_formula[i] == '(':
# 左括号
element = "paren"
element_type = "lepa"
subscription, step, subscription_end = find_subscription(chemic_formula, i, element_type)
# 其下标, 元素的结束位置, 下标的结束位置
if element == "paren":
all_elements += rtn_result(chemic_formula[i+1: i+step-1]) * int(subscription)
# 如果是括号则递归调用自己,最后返回括号内的所有元素再乘以下标
else:
all_elements += element * int(subscription)
i = subscription_end
# 直接跳到下一个元素的开始位置
if (chemic_formula[i]) == '.':
# 如果跳到最后的位置则结束
print('* break from: ', chemic_formula)
break
return all_elements * int(formula_coefficient)
if __name__ == "__main__":
expression_num = int(input())
for en in range(expression_num):
expression = input()
former_expression, later_expression = expression.split('=')
all_former_fomula = former_expression.split('+')
all_later_formula = later_expression.split('+')
sum_former = []
sum_later = []
for ff in all_former_fomula:
sum_former += rtn_result(ff)
sum_former.sort(key=None, reverse=False)
for lf in all_later_formula:
sum_later += rtn_result(lf)
sum_later.sort(key=None, reverse=False)
if sum_former == sum_later:
print('Y')
else:
print('N')
测试用例
11
H2+O2=H2O
Cu+As=Cs+Au
H2+Cl2=2NaCl
2H2+O2=2H2O
H2+Cl2=2HCl
CH4+2O2=CO2+2H2O
CaCl2+2AgNO3=Ca(NO3)2+2AgCl
3Ba(OH)2+2H3PO4=6H2O+Ba3(PO4)2
3Ba(OH)2+2H3PO4=Ba3(PO4)2+6H2O
4Zn+10HNO3=4Zn(NO3)2+NH4NO3+3H2O
4Au+8NaCN+2H2O+O2=4Na(Au(CN)2)+4NaOH
NNNYYYYYYYY
13
AAAAAAA=AAAAAAA
AaAaAaAa=AaAaAaAa
ABCDEFG=GFEDCBA
AaABbBCcCDdDEeEFfFGgG=GgGFfFEeEDdDCcCBbBAaA
2AAAAAA=3AAAA
2AaAAaAAaAAaAAaAAaA=3AaAAaAAaAAaA
(((((((((((((A)))))))))))))=(((((((((((((A)))))))))))))
(((((((((((((Aa)))))))))))))=(((((((((((((Aa)))))))))))))
(((((((((((((AaA)))))))))))))=(((((((((((((AAa)))))))))))))
(((((((((((((A)13)12)11)10)9)8)7)6)5)4)3)2)1=1(2(3(4(5(6(7(8(9(10(11(12(13(A)))))))))))))
(((((((((((((A)1)12)3)10)5)8)7)6)9)4)11)2)13=1(12(3(10(5(8(7(6(9(4(11(2(13(A)))))))))))))
(A)(A)(A)(A)(A)(A)(A)=(A)(A)(A)(A)(A)(A)(A)
3A(A(A(A(A(((A))B2)2AB)2A)2A)2A)2A=3AA+6AA+12AA+24AA+48AAB+96ABB
YYYYYYYYYYYYY