CCF CSP 201912-3 化学方程式(python)满分
提交截图:
样例输入:
11
H2+O2=H2O
2H2+O2=2H2O
H2+Cl2=2NaCl
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
Cu+As=Cs+Au
输出:
N
Y
N
Y
Y
Y
Y
Y
Y
Y
N
解析:每一种原子的个数是化学式前的系数与原子后的系数相乘,因为有括号的存在,难点在于如何提取系数。
思路:计算每一个原子的个数,由外向里提取系数相乘,用一个系数列表来存储每一个原子的系数,每一个原子的初始系数为化学式前的系数。例如10HNO3,那么系数列表一共有两步,
第一步:H:10,N:10,O:10
第二步:H:10,N:10,O:30
因为O原子后面跟着数字3,则第二步的时候,O:10x3
例如:32Ba((OH)2(CO3)2)3,那么系数列表的变化为:
初始系数列表,所有元素的系数为化学式首部系数
第一步:Ba:32,O:32,H:32,C:32,O:32
先算外面的括号,乘以括号外的系数3,由于Ba不在括号内,所以Ba的系数不变
第二步:Ba:32,O:96,H:96,C:96,O:96
之后再算里面的括号外的系数,由于(OH)2在前所以先算(OH)2
第三步:Ba:32,O:192,H:192,C:96,O:96
由于OH后面的系数都为1所以直接计算(CO3)2
第四步:Ba:32,O:192,H:192,C:192,O:192
(CO3)2中,O原子后面跟着系数3,所以O元素的系数再乘3
第五步:Ba:32,O:192,H:192,C:192,O:576
计算完(CO3)2后,就没有左括号和原子了,所以系数列表就经过5步变化,之后将相同元素的个数相加即可
源码:
#====将字数型数字变为整型=================================
def Intnumber(list):#将字符型数字,变成整型
m=len(list)
i=0
h=0
while 1:
if '0'<=list[i]<='9':
c=list[i]
while '0'<=list[i+1]<='9':
h+=1
c+=list[i+1]
del list[i+1]
list[i]=int(c)
i+=1
if i==m-1-h:
break
return list
#===初始化系数列表====================================
def Cftlist(x,list):#系数列表
for i in list:
clist.append([i,x])
return clist
m = int(input())
for i in range(m):
n = input()
left = []
right = []
z1 = {}
z2 = {}
n_l, n_r = n.split('=')
n_l = n_l.split('+')
n_r = n_r.split('+')
#=========处理化学式方程式========================================
for t in n_l, n_r:
z3 = {}
for j in t:
ls = []
k = 0
j = j + '-'#字符串后加一个非字母数字的符号,防止溢出
while k <= len(j) - 2:
if str(j[k + 1]).islower():#处理含小写字母的元素
ls.append(j[k] + j[k + 1])
z3[j[k] + j[k + 1]] = 0#将元素存于字典
k += 2
else:
ls.append(j[k])
if str(j[k]).isalpha():#将化学元素存于字典
z3[j[k]] = 0
k += 1
if t is n_l:
left.append(ls)
z1 = z3
else:
right.append(ls)
z2 = z3
if z1!=z2:
print('N')
continue
#=========计算化学式的原子个数=============================
clist = []
for h in left,right:
for v in h:
v.append('-')#防止列表超出
v=Intnumber(v)#字符型数字,变成整型
x=1
if str(v[0]).isdigit():
x=v[0]
clist=Cftlist(x,v)#初始化系数列表
for k in range(len(v)):
if str(v[k]).isalpha():#处理系数在原子后面的情况
if str(v[k+1]).isdigit():
clist[k][1] *= v[k + 1]
a, b = 0, 0
if v[k] == '(':#处理系数在括号外的情况
a += 1
while a > 0:
b += 1
if v[k+b] == '(':
a += 1
elif v[k+b] == ')':
a -= 1
if str(v[k+b+1]).isdigit():#括号内的元素的系数相乘
for t in range(k, k + b):
clist[t][1] *= v[k + b + 1]
if h is left:#左边化学式的元素总数
for t in range(len(clist)):
if clist[t][0] in z1:
z1[clist[t][0]] += clist[t][1]
else:#右边化学式的元素总数
for t in range(len(clist)):
if clist[t][0] in z2:
z2[clist[t][0]] += clist[t][1]
clist=[]
if z1 == z2:
print('Y')
else:
print('N')