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. 解决获取IP地址时出现“在一个非套…

    今天单位的一台机器在用IPCONFIG/RENEW时遇到了这个问题,上网查了一下,网上的版本在对XP不太好用,网上的版本如下: 1.从注册表中备份以下项:(当然也可以用Erunt备份整个注册表)HKE ...

  2. 获取设备、APP的一些信息

    获取设备的一些信息: UIDevice *device = [UIDevice currentDevice]; @property(nonatomic,readonly,strong) NSStrin ...

  3. C# 中的常用正则表达式大全

       这是从网上找来的,收藏一下备用,用到之处可以节省不少时间哦! 只能输入数字: "^[0-9]*$" . 只能输入n位的数字:"^\d{n}$". 只能输入 ...

  4. linux学习笔记之硬盘分区

    引用:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/03/2997098.html PS:本文仅对知识点作总结.详情请参考原文. 首先 ...

  5. Lifting the Stone(hdoj1115)

    Lifting the Stone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  6. keepalived 安装和配置

    第一步:安装 yum -y install keepalived 第二步:配置 /etc/keepalived/keepalived.conf ! Configuration File for kee ...

  7. Linux下Nginx+PHP 简单安装配置

    测试环境 Linux 2.6.18nginx-1.0.4 http://www.nginx.org/php-5.3.6 http://www.php.net/ 一,安装Nginxwget http:/ ...

  8. EasyUI 使用

    1.面板的使用 <div id="box" > <p>内容区域</p> </div> <div id="tt&quo ...

  9. ASP.NET抓取网页内容的实现方法

    这篇文章主要介绍了ASP.NET抓取网页内容的实现方法,涉及使用HttpWebRequest及WebResponse抓取网页内容的技巧,需要的朋友可以参考下 一.ASP.NET 使用HttpWebRe ...

  10. windows窗口分析,父窗口,子窗口,所有者窗口

    (本文尝试通过一些简单的实验,来分析Windows的窗口机制,并对微软的设计理由进行一定的猜测,需要读者具备C++.Windows编程及MFC经验,还得有一定动手能力.文中可能出现一些术语不统一的现象 ...