CSP-化学方程式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

思路:

根据题意知:除了第一个数字,其他数字都是出现在元素后面的,除了有括号的情况,其他出现数字的情况,该数字只针对于它前面的一个化学元素。
1.先将输入的一条化学方程式按 ‘=’ 隔开,然后用同样的方式分别处理左右俩边的式子,利用字典存放每个元素及其数量,最后比较一下就可以。
2.对与每边的式子,用 ’ + '分隔成单独的字符串,再用同样的方式处理这些字符串。
3.对于每个字符串,先存放它最前面的系数,然后用俩个栈,一个是存放元素的elements,一个是存放数量的num,每存一个元素也相应的存入该元素的数量为1,如果遇到数字并且不是在右括号后面的话,就将数量栈中的最后一个元素值改为它本身乘这个数。如果遇到左括号也将左括号加入元素栈中,如果遇到右括号的话,先看右括号后面有没有数字,有的话计算该数字 t ,没有的话默认为1,设置一个index= -1,然后向前遍历elements栈直到遇到一个左括号,然后向前遍历过程中也修改数量栈中对应位置的元素num[index] *= t,遇到左括号,将左括号删除。
代码(样例测试正确,提交之后只有90分,目前也还没找到错误…):

def judge(c):
    if c >= '0' and c <= '9':
        return 1
    if c >= 'A' and c <= 'Z':
        return 2
    if c >= 'a' and c <= 'z':
        return 3
    if c == '(':
        return 4
    if c == ')':
        return 5
def count_ele(s:str):
    # 存放每个元素及其数量
    t_map = {}
    str_l = s.split('+')
    for temp in str_l:
        # 存放最前面的系数,不一定是个位数
        head = 0
        # 每个元素的对应的数量栈
        num = []
        # 元素栈
        elements = []
        i = 0
        lens = len(temp)
        # 计算前面的系数
        while judge(temp[i]) == 1:
            head = head*10 + int(temp[i])
            i += 1
        head = 1 if head == 0 else head
        # 存放除去头节点之外的数字
        temp_head = 0
        # 判断前面是否有数字
        flag = False
        while i < lens:
            while i < lens and judge(temp[i])==1:
                temp_head = temp_head*10 + int(temp[i])
                i += 1
                flag = True
            else:
                if flag:
                    num[-1] = num[-1]*temp_head
                    temp_head = 0
                    flag = False
                if i >= lens:
                    continue
                if judge(temp[i]) == 2:
                    # 如果这个元素由一个大写字母一个小写字母组成
                    if i+1<lens and judge(temp[i+1]) == 3:
                        # 将该元素加入elements栈中
                        elements.append(temp[i]+temp[i+1])
                        num.append(1)
                        i += 2
                        continue
                    # 如果只由一个字母组成
                    else:
                        elements.append(temp[i])
                        num.append(1)
                        i += 1
                        continue
                # 如果是左括号
                if judge(temp[i]) == 4:
                    elements.append(temp[i])
                    i += 1
                    continue
                # 如果遇到右括号
                if judge(temp[i]) == 5:
                    # 存放括号后面的数字
                    t = 0
                    i += 1
                    # 计算括号后面的数
                    while i < lens and judge(temp[i])==1:
                        t = t * 10 + int(temp[i])
                        i += 1
                    t = 1 if t == 0 else t
                    k = -1
                    while elements[k] != '(':
                        num[k] = num[k]*t
                        k -= 1
                    # 删除左括号,remove是根据值删除,pop根据索引删除
                    elements.pop(k)
        len_e = len(elements)
        # 将每个元素的数量加入字典中,记得要乘头部的系数
        for j in range(len_e):
            if elements[j] not in t_map:
                t_map[elements[j]] = num[j]*head
            else:
                t_map[elements[j]] += num[j]*head
    return t_map
n = int(input())
strings = []
for i in range(n):
    strings.append(input())
for i in range(n):
    left,right = strings[i].split('=')
    map_l = count_ele(left)
    map_r = count_ele(right)
    flag = True
    for k in map_l.keys():
        if k not in map_r:
            flag = False
            break
        else:
            if map_l[k] != map_r[k]:
                flag = False
                break
    if flag:
        print('Y')
    else:
        print('N')
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值