For a given chemical formula represented by a string, count the number of atoms of each element contained in the molecule and return an object.

 water = 'H2O'
 parse_molecule(water)
 # return {H: 2, O: 1} 

 magnesium_hydroxide = 'Mg(OH)2' parse_molecule(magnesium_hydroxide)
 # return {Mg: 1, O: 2, H: 2}

 var fremy_salt = 'K4[ON(SO3)2]2'
 parse_molecule(fremySalt)
 # return {K: 4, O: 14, N: 2, S: 4}

这个题大意就是将分子表达式转化成原子(词典表示),在codewars上难度是3kyu,难点在于各种条件的分析,防止越界,还有分子式中的各种限制。

我的思路大概就是把方括号,大括号都转换成括弧先,依次把最内层,然后外层的括弧展开,最后得到一个没有括弧的表达式,这就很好处理了。这里有个寻找最内层括弧的问题,我的理解是,先找到第一个')',然后往前找与之对应的'(',用展开后的结果代替'(...)2',我用2代替括弧后面的数字,有可能这个数字是1,自然就省略了,我们要在转换过程中把1补上。在最后的处理中,我们也要注意1是被省略的,需要计算时加上。

代码如下:

 def parse_molecule(formula):
     formula_dict = {}
     #替换[]{}为()
     for bracket in '[{':
         formula = formula.replace(bracket, '(')
     for bracket in ']}':
         formula = formula.replace(bracket, ')')

     if '(' in formula:
         has_bracket = True
     else:
         has_bracket = False
     while has_bracket:
         #寻找最内层的()
         for i in range(len(formula)):
             if formula[i] == ')':
                 break
         for j in range(len(formula[:i])-1, -1, -1):
             if formula[j] == '(':
                 break
         #如果有省略的1,补上
         if i+1 == len(formula) or not formula[i+1].isdigit():
             sub_formula = formula[j: i+1]
             #为了防止后面的replace出错,设置了临时变量,否则
             #如果直接sub_formula = formula[j: i+1] + '1'
             #sub_formula变成了formula中没有的子串,就不执行
             #这个循序就会一直进行下去
             tmp = sub_formula + '
         else:
             sub_formula = formula[j: i+2]
             tmp = sub_formula
         parsed_sub_formula = parse_paren(tmp)
         formula = formula.replace(sub_formula, parsed_sub_formula)
         if '(' in formula:
             has_bracket = True
         else:
             has_bracket = False
     #处理没有()的分子表达式
     i = 0
     while i < len(formula):
         j = i+1
         if j < len(formula) and formula[j].islower():
             j += 1
         tmp = formula[i: j]
         #注意边界的处理防止j越界
         #我这里有个小bug,我假设的是原子下标都是最多两位,如果出现三位
         #就会把第三位当做一个元素且下标为1
         #没想到也通过了
         if j < len(formula) and formula[j].isdigit():
             k = j+1
             if k < len(formula) and formula[k].isdigit():
                 formula_dict[tmp] = formula_dict.get(tmp, 0) + int(formula[j: k+1])
                 i = k+1
             else:
                 formula_dict[tmp] = formula_dict.get(tmp, 0) + int(formula[j])
                 i = j+1
         elif j < len(formula) and formula[j].isupper():
             formula_dict[tmp] = formula_dict.get(tmp, 0) + 1
             i = j
         elif j == len(formula):
             formula_dict[tmp] = formula_dict.get(tmp, 0) + 1
             break

     return formula_dict

 def parse_paren(sub_formula):
     result = {}
     times = int(sub_formula[-1])
     i = 1
     while i < len(sub_formula)-2:
         j = i+1
         if sub_formula[j].islower():
             j += 1
         tmp = sub_formula[i: j]
         if sub_formula[j].isdigit():
             k = j+1
             #此处也是假设原子下标为最多两位
             if k < len(sub_formula)-2 and sub_formula[k].isdigit():
                 result[tmp] = result.get(tmp, 0) + int(sub_formula[j: k+1])*times
                 i = k+1
             else:
                 result[tmp] = result.get(tmp, 0) + int(sub_formula[j])*times
                 i = j+1
         elif sub_formula[j].isupper() or sub_formula[j] == ')':
             result[tmp] = result.get(tmp, 0) + 1*times
             i = j

     t = []
     for key, val in result.iteritems():
         t.append(key)
         t.append(str(val))
     return ''.join(t)

 #测试的时候故意加了一些乱七八糟的分子表达式,但还符合规则
 print parse_molecule('K4[ON(SO3)2]2')
 print parse_molecule('(H2O)H10')
 print parse_molecule('(OH123)2')    

虽然也通过了,但是代码中的bug有时间再改(不知何时了,反正被折磨得够呛,下次下次......水平太差了)

不过好像用正则表达式更好的样子,那就stay tuned...

Molecule to atoms的更多相关文章

  1. Haskell语言学习笔记(64)Lens(4)

    安装 lens-tutorial Control.Lens.Tutorial $ cabal install lens-tutorial Installed lens-tutorial-1.0.3 P ...

  2. Molecule – 帮助你构建跨平台的 HTML5 游戏

    Molecule 框架由拥有超过五年手机游戏开发经验的游戏开发者开发.由于移动浏览器与实际的 HTML5 规范的兼容性的改进和内部硬件的自然进化,HTML5 手机游戏真正有可能流行起来. 您可能感兴趣 ...

  3. Yandex 2013Q(Atoms: There and Back Again-贪心+模拟+List)

    Atoms: There and Back Again Time limit 2 seconds Memory limit 256Mb Input stdin Output stdout Legend ...

  4. 【LeetCode】726. Number of Atoms 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/number-o ...

  5. Molecule实现数栈至简前端开发新体验

    Keep It Simple, Stupid. 这是开发人耳熟能详的 KISS 原则,也像是一句有调侃意味的善意提醒,提醒每个前端人,简洁易懂的用户体验和删繁就简的搭建逻辑就是前端开发的至简大道. 这 ...

  6. [LeetCode] Number of Atoms 原子的个数

    Given a chemical formula (given as a string), return the count of each atom. An atomic element alway ...

  7. [Swift]LeetCode726. 原子的数量 | Number of Atoms

    Given a chemical formula (given as a string), return the count of each atom. An atomic element alway ...

  8. LeetCode Number of Atoms

    原题链接在这里:https://leetcode.com/problems/number-of-atoms/description/ 题目: Given a chemical formula (giv ...

  9. Error (167005): Can't assign I/O pad "GX_TX" to PIN_AG27 because this causes failure in the placement of the other atoms in its associated channel

    1.同时在两个GX的bank,建立两GX ip core 会出现 两个IP的cal_blk_clk信号,要保持是同一个时钟

随机推荐

  1. pl sql练习(4)

    1.ROW_NUMBER 返回连续的排位,不论值是否相等 select deptno,ename,sal, row_number () over (partition by deptno order ...

  2. Oracle 10G 使用UTL_SMTP发送中文电子邮件[Z]

    CREATE OR REPLACE PROCEDURE SCOTT.HTML_EMAIL( P_TO IN VARCHAR2, --收件人地址 P_SUBJECT IN VARCHAR2, --邮件主 ...

  3. HDU 1071 - The area

    求曲线和直线围成的面积 求表达式,求积分 #include <iostream> using namespace std; ],y[]; int t; double k,m;//fx1: ...

  4. vs2012配置opencv及简单测试

    为visual studio2012搭建openCV平台,实现打开图片. 实现步骤: 1.1.配置环境变量 基于win7操作系统的环境配置步骤: 1.1.1 计算机—>属性—>更改设置—& ...

  5. activity的生命周期详解

    刚在看mars老师的视频,看到activity的生命周期,就看了一下,总结了一下.下面是各函数的调用时机 为了更清楚的看清楚工作的具体过程,举例如下: ,建立两个activity,一个main,一个a ...

  6. jQuery插件的点点滴滴

    说起jQuery插件,很多人的脑海种已经有了一定的雏形,仿佛感觉仅仅就是那样子,事实呢?当你看了Bootstrap.js,品读了slidesjs,观摩了jquery.cycle2.js,不禁发现,原来 ...

  7. PHP解决网站高流量高并发问题

    首先,确认服务器硬件是否足够支持当前的流量. 普通的P4服务器一般最多能支持每天10万独立IP,如果访问量比这个还要大, 那么必须首先配置一台更高性能的专用服务器才能解决问题 ,否则怎么优化都不可能彻 ...

  8. Oracle EBS-SQL (PO-18):检查工作台下达的PR在系统找不到.sql

    select * From apps.po_requisitions_interface_all---------------------------------------------------- ...

  9. [python] 如何用python操作Excel

    直接上代码: from openpyxl import Workbook from openpyxl.cell import get_column_letter wb = Workbook() des ...

  10. sql server遍历表不用游标和临时表的方法

    表结果如图 )) ,'Sky,Blue,Water' ,'Book,Apple,Shirt' ,'Cup,Yellow,org' ,'box,phone,paper' GO SELECT id,SUB ...