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. Unity IOC注入详细配置(MVC,WebApi)

    一直想写一篇关于unity 详细的配置信息的文章,也算是自我总结吧 先介绍了unity , Unity是微软官方推荐使用的轻型的IOC框架,支持各种方式的注入 ,使用来解耦的利器. 获取unity 的 ...

  2. android spinner 每行字体颜色都变化

    final static int[] COLOR_LIST={Color.WHITE,Color.WHITE,Color.GRAY,Color.YELLOW,Color.RED}; spinner=( ...

  3. OA、CRM、ERP之间的区别和联系是什么?

    我们假设你是某机械行业的销售,一切从今天你收到公司的邮件,去上海参加展会开始 因为 去展会 所有 首先 你打开 OA 登陆 填写出差申请表 送交主管审批 填表--审批--行政订票酒店 然后呢 你飞去上 ...

  4. jquery操作session的方法

    jquery.session.js使用  //此方法在java中不能使用 // jquery.session.js 简单使用方法 添加数据    $.session.set('key', 'value ...

  5. Java API设计CheckList

    API设计原则:正确.好名.易用.易学.够快.够小.但我们从来不缺原则,〜〜〜 Interface 1.The Importance of Being Use Case Oriented,一个接口应当 ...

  6. MSSQL 获取数据库字段类型

    SELECT col.name AS 列名, typ.name as 数据类型, col.max_length AS 占用字节数, col.precision AS 数字长度, col.scale A ...

  7. 流程控制 - PHP手册笔记

    脚本由语句构成,语句靠流程控制实现功能,这一节主要介绍了几个关键字的使用. elseif elseif和else if的行为完全一样,如果用冒号来定义if/elseif条件,那就不能用两个单词的els ...

  8. Hibernate: merge方法

    在Hibernate中,有save.persist.savaOrUpdate.merge等方法有插入数据的功能.前三者理解起来较后者容易一些,merge方法从api中的介绍就看以看出它是最复杂的.下面 ...

  9. DPark安装及相关资料整理

    最近需要处理海量数据的分布式计算及数据挖掘,经过多次选择(hadoop,Spark,DPark),最后还是选择了DPark,主要是看中DPark的轻量级及python的灵活性,且除了豆瓣外,在几个友公 ...

  10. QT父子与QT对象delete

    原地址:http://www.qteverywhere.com/archives/437 很多C/C++初学者常犯的一个错误就是,使用malloc.new分配了一块内存却忘记释放,导致内存泄漏.Qt的 ...