美文网首页
ccf-201912-3-化学方程式-python版本(正则、递

ccf-201912-3-化学方程式-python版本(正则、递

作者: hodit | 来源:发表于2020-02-28 00:51 被阅读0次

    题目

    题目
    输入、输出格式
    测试点

    说明

    最近学了点正则原打算用正则做,但是在括号嵌套方面正则表达式不懂处理,栈方面不熟悉就还没考虑。匹配化学元素和系数可以一个个字符处理没必要用正则,这里我是练习所以用了正则。
    这道题的解题思路大多采用递归求解这里也是(如果有同学有其他思路请留言一起学习~~~),这题麻烦点的地方在于括号嵌套处理 。大体思路是 比如“CH4+2O2=CO2+2H2O”,用“=”切片分左右两部分,用”+“切片递归处理每一个化学式。
    处理化学式思路是:化学式是字符串,利用索引从左到右一点一点处理直到字符串结束。遇到无括号直接是元素的就添加进记录,遇到括号就递归。

    输入样例

    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      
    

    代码

    import re
    pattern_ele = re.compile(r'[A-Z][a-z]?') #匹配化学元素的模式
    pattern_lc = re.compile(r'^\d+') #匹配左边系数的模式
    pattern_rc = re.compile(r'\d+$') #匹配右边系数的模式
    pattern_term = re.compile(r'^[A-Z][a-z]?\d*') #匹配化学式中的项(元素部分)和系数
    #该函数用于处理系数和化学式
    '''
    if:处理测试编号点1-6
    elif/else:处理测试编号点7-10
    '''
    def deal_formula(ceof,formula,dic):
        i = 0
        while i < len(formula):
            term = pattern_term.match(formula[i:])
            if  term != None: #处理未出现括号的情况
                term = term.group()
                if term[-1].isdigit(): #处理如 Na2CO3 的情况
                    r_ceof = pattern_rc.search(term)[0]
                    ele = term[:-len(r_ceof)]
                    deal_ele(ceof * int(r_ceof),ele,dic)
                else: #处理如 CaCO3 的情况
                    deal_ele(ceof,term,dic)
                i += len(term)
    
            else:#处理出现括号以及括号嵌套的情况:如 (NH4)2CO3、Na(Au(CN)2)
                begin = i + 1
                end = begin
                close = 1 
                while end < len(formula):
                    if formula[end] == '(':
                        close += 1
                    elif formula[end] == ')':
                        close -= 1
                    if close == 0:
                        break
                    end += 1
                if end + 1< len(formula) and formula[end+1].isdigit():
                    r_ceof = pattern_lc.match(formula[end+1:])[0]
                    deal_formula(ceof * int(r_ceof),formula[begin:end],dic)
                    end += len(r_ceof)
                else:
                    deal_formula(ceof,formula[begin:end],dic)
                i = end + 1
    #处理元素                                 
    def deal_ele(ceof,element,dic):
        dic[element] += ceof
    
    #处理表达式
    def deal_expr(expr):
        ceof = 1
        formula = expr
        if expr[0].isdigit():
            ceof_str = pattern_lc.match(expr)[0]
            ceof = int(ceof_str)
            formula = expr[len(ceof_str):]
        return ceof,formula
    
    #校验化学方程式       
    def checkEquation(equation):
        ele_dic = [{},{}]
        expr_list = [[],[]]
        exprs = equation.split("=")
    
        for i in range(2):
            eles = set(pattern_ele.findall(exprs[i]))
            for j in eles:
                ele_dic[i][j]=0
                
        if ele_dic[0] != ele_dic[1]:
            print('N')
            return None
        for i in range(2):
            expr_list[i] = exprs[i].split('+')
            for j in expr_list[i]:
                ceof,formula = deal_expr(j)
                deal_formula(ceof,formula,ele_dic[i])
        if ele_dic[0] == ele_dic[1]:
            print('Y')
        else:
            print('N')
            
    
    def main():
        n = int(input())
        lists = []
        for i in range(n):
            equation = input()
            lists.append(equation)
        for i in lists:
            checkEquation(i)
    
    main()
    

    相关文章

      网友评论

          本文标题:ccf-201912-3-化学方程式-python版本(正则、递

          本文链接:https://www.haomeiwen.com/subject/asuqhhtx.html