Advertisement
Vermiculus

Untitled

Mar 18th, 2012
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. def d(s):
  2.     raw_input("----DEBUG----{0}".format(s))
  3.  
  4. # Class Molecule:
  5. #   elements: a dictionary of elements and their subscripts
  6. #   count: the coefficient on the molecule
  7. class Molecule:
  8.     class Atomic: # Represents a {Element}_{Subscript} structure (no coefficient)
  9.         def __init__(self, el, sub):
  10.             self.element = el
  11.             self.subscript = sub
  12.         def getElement(self):
  13.             return self.element
  14.         def getSubscript(self):
  15.             return self.subscript
  16.  
  17.     def __init__(self):
  18.         self.elements = dict()
  19.         self.count = 1
  20.  
  21.     def __str__(self):
  22.         ret = "{"+str(self.count)+"}"
  23.         for el in self.elements:
  24.             ret += "[{0}_{1}]".format(el,self.elements[el])
  25.         return ret
  26.  
  27.     def getElementTotals(self):
  28.         ret = dict()
  29.         for el in self.elements.keys():
  30.             ret[el] = self.elements[el] * self.count
  31.         return ret
  32.  
  33.     def add(self, atomic):
  34.         self.add(atomic.getElement(), atomic.getSubscript())
  35.  
  36.     def add(self, element, subscript):
  37.         # if the molecule already contains this element, just increase the subscript
  38.         if element in self.elements:
  39.             self.elements[element] += subscript
  40.         else: # otherwise, add the element and its subscript
  41.             self.elements[element] = subscript
  42.    
  43.     def fold(self, mol):
  44.         for el in mol.elements.keys():
  45.             self.add(el, mol.elements[el] * mol.count)
  46.  
  47. def getWord(s,i): # Returns a [isElem, token, lastIndex] list from a string s starting at index i
  48.     if i >= len(s) or i < 0:
  49.         return Nothing
  50.    
  51.     ret = s[i]
  52.     isElem = ret.isalpha()
  53.     i += 1
  54.     while i < len(s):
  55.         #d(str((isDigit, s[i], i, ret)))
  56.         if not isElem:
  57.             if s[i].isdigit():
  58.                 ret += s[i]
  59.             else:
  60.                 return [isElem,ret,i]
  61.         else:
  62.             if s[i].isupper() or s[i].isdigit():
  63.                 return [isElem,ret,i]
  64.             else:
  65.                 ret += s[i]
  66.         i = i + 1
  67.     return [isElem,ret,i]
  68.  
  69. def tokenize(s):
  70.     l = list()
  71.     i = 0
  72.     while i < len(s):
  73.         newi = getWord(s, i)
  74.         i = newi[2]
  75.         l.append(newi)
  76.     return l
  77.  
  78. def standardize(tokens): # inserts implicit subscripts and puts them into ints
  79.     if tokens[0][0]:
  80.         tokens.insert(0,[False,1,0])
  81.     i = 0
  82.     while i < len(tokens):
  83.         if tokens[i][0]: # if this is an element
  84.             if i+1 == len(tokens):
  85.                 tokens.append([False,1,tokens[i][2]])
  86.             elif tokens[i+1][0]: # if the next is also an element (ie not a subscript)
  87.                 tokens.insert(i+1,[False,1,tokens[i][2]])
  88.         else: # if this was a subscript
  89.             tokens[i][1] = int(tokens[i][1])
  90.         i = i + 1
  91.    
  92.     return tokens
  93.  
  94. def molecularize(tokens):
  95.     mol = Molecule()
  96.     mol.count = tokens[0][1]
  97.     for i in range(1,len(tokens),2):
  98.         mol.add(tokens[i][1], tokens[i+1][1])
  99.     return mol
  100.  
  101. def pl(l):
  102.     for n in l:
  103.         print n
  104.  
  105. def getmol(s): # returns a Molecule from a string
  106.     tok = tokenize(s)
  107.     standardize(tok)
  108.     mol = molecularize(tok)
  109.     return mol
  110.  
  111. def fission(s): # splits a string 'A=B' up into molecular components [[A1,A2,...],[B1,B2,...]
  112.     lnr = s.split('=')
  113.     if len(lnr) != 2:
  114.         print 'error'
  115.         return Nothing
  116.     left = lnr[0].split('+')
  117.     right = lnr[1].split('+')
  118.    
  119.     lmols = list()
  120.     for m in left:
  121.         lmols.append(getmol(m))
  122.    
  123.     rmols = list()
  124.     for m in right:
  125.         rmols.append(getmol(m))
  126.    
  127.     return [lmols,rmols]
  128.  
  129. def fusion(lnr): # takes the output of fission and folds them for balancing
  130.     if len(lnr) != 2:
  131.         print 'error'
  132.         return Nothing
  133.    
  134.     for side in lnr:
  135.         for i in range(1,len(side)):
  136.             side[0].fold(side[i])
  137.    
  138.     return [lnr[0][0], lnr[1][0]]
  139.    
  140. def balance(s):
  141.     print "fission"
  142.     fis = fission(s)
  143.     for side in fis:
  144.         pl(side)
  145.     print "fusion"
  146.     fus = fusion(fis)
  147.     pl(fus)
  148.    
  149.     l = fus[0].getElementTotals()
  150.     r = fus[1].getElementTotals()
  151.    
  152.     return l == r
  153.  
  154. print balance("H2O+H2O=2H2O")
  155. # to do the function multiple times, map(balance, input.split())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement