mirror of
https://github.com/heqin-zhu/algorithm.git
synced 2024-03-22 13:30:46 +08:00
82 lines
2.2 KiB
Python
82 lines
2.2 KiB
Python
import re
|
|
from collections import namedtuple
|
|
left = r'(?P<LEFT>\()'
|
|
right = r'(?P<RIGHT>\))'
|
|
word = r'(?P<WORD>[A-Z][a-z]*)'
|
|
num = r'(?P<NUM>\d+)'
|
|
pt = re.compile('|'.join([left, right, word, num]))
|
|
|
|
token = namedtuple('token', ['type', 'value'])
|
|
|
|
|
|
def genToken(s):
|
|
scanner = pt.scanner(s)
|
|
for i in iter(scanner.match, None):
|
|
yield token(i.lastgroup, i.group(0))
|
|
|
|
|
|
class parser:
|
|
'''grammar:
|
|
S-> item | S item
|
|
item -> word | word num | '(' S ')' num
|
|
'''
|
|
|
|
def match(self, curType):
|
|
sym = self.token[self.lookahead]
|
|
if sym.type == curType:
|
|
self.lookahead += 1
|
|
return sym.value
|
|
raise Exception('Invalid input string')
|
|
|
|
def parse(self, s):
|
|
self.token = [i for i in genToken(s)]
|
|
self.lookahead = 0
|
|
return self.S()
|
|
def S(self):
|
|
dic = {}
|
|
while self.lookahead < len(self.token) and self.token[self.lookahead].type != 'RIGHT':
|
|
cur = self.item()
|
|
for i in cur:
|
|
if i in dic:
|
|
dic[i] += cur[i]
|
|
else:
|
|
dic[i] = cur[i]
|
|
return dic
|
|
|
|
def item(self):
|
|
if self.token[self.lookahead].type == 'WORD':
|
|
ele = self.match('WORD')
|
|
n = 1
|
|
if self.lookahead < len(self.token) and self.token[self.lookahead].type == 'NUM':
|
|
n = int(self.match('NUM'))
|
|
return {ele: n}
|
|
elif self.token[self.lookahead].type == 'LEFT':
|
|
self.match('LEFT')
|
|
dic = self.S()
|
|
self.match('RIGHT')
|
|
n = int(self.match("NUM"))
|
|
for i in dic:
|
|
dic[i] *= n
|
|
return dic
|
|
else:
|
|
print(self.token[self.lookahead])
|
|
raise Exception('invalid string')
|
|
|
|
|
|
class Solution(object):
|
|
def countOfAtoms(self, formula):
|
|
"""
|
|
:type formula: str
|
|
:rtype: str
|
|
"""
|
|
dic = parser().parse(formula)
|
|
return ''.join(c+str(dic[c]) if dic[c] != 1 else c for c in sorted(dic.keys()))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
li = ["K4(ON(SO3)2)2","Mg(OH)2"]
|
|
sol = Solution()
|
|
for s in li:
|
|
print('>>>',s)
|
|
print(sol.countOfAtoms(s))
|