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. 疯狂Android第二章:Adapter以及部分控件使用

    第二章 重点:1.理解View以及各种布局的优缺点,适用场景. 2.熟练掌握adapter原理与用法. 3.熟悉其它控件的基本使用方法. /////////////////////////////// ...

  2. C#面试题总结——程序设计基础

    一.类型与变量 1.C#支持哪几个预定义的值类型? 主要包括五个类型:整数,浮点数,字符型,bool类型以及decimal型(小数型).其中每一个类型分别有多个内置类型组成. 2.C#支持哪几个预定义 ...

  3. oracle 如何搜索当前用户下所有表里含某个值的字段?(转)

    oracle 如何搜索当前用户下所有表里含某个值的字段? create or replace procedure MY_Pro_SearchKeyWord is  v_sql VARCHAR2(400 ...

  4. jsp基础之 jstl

    JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标签. 除了这些,它还提供 ...

  5. HDU 1088 - Write a simple HTML Browser

    直接看sample input = = 又一道模拟. #include <iostream> #include <string> #include <cstdio> ...

  6. 在Yii框架中使用PHPExcel

    PHPExcel是一个比较好用的php读取excel文件的类库,今天遇到了在yii中如何加载PHPExcel类文件的问题,因为Yii的autoload机制是安装类名去找文件,即文件名就是相应的类名,而 ...

  7. windows查询端口

    依次点击“开始→运行”,键入“cmd”并回车,打开命令提示符窗口.在命令提示符状态下键入“netstat -an”,按下回车键后就可以看到以数字形式显示的TCP和UDP连接的端口号及状态.

  8. github proxy

    --set github proxy git config --global http.proxy http://user_name:user_pwd@user_ip:port git config  ...

  9. %hd %d %ld %u ......

    %d 有符号10进制整数 %ld 长整型 %hd短整型%md,m指定的是输出字段的宽度,默认左补空格, 如果数据的位数小于m,则左端补以空格,若大于m,则 按实际位数输出,如: printf(&quo ...

  10. Drawable复习—第六章

    一.Drawable的分类及使用 复习知识:①.Drawable有几种类别. ②.在哪里利用xml创建Drawable  ③.类中各个类别如何使用  ④.Drawable的插值器和设置时常.是否保持动 ...