Advertisement
Vermiculus

Untitled

Mar 18th, 2012
87
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.         self.elements = self.getElementTotals()
  45.         self.count = 1
  46.         for el in mol.elements.keys():
  47.             self.add(el, mol.elements[el] * mol.count)
  48.  
  49. def getWord(s,i): # Returns a [isElem, token, lastIndex] list from a string s starting at index i
  50.     if i >= len(s) or i < 0:
  51.         return Nothing
  52.    
  53.     ret = s[i]
  54.     isElem = ret.isalpha()
  55.     i += 1
  56.     while i < len(s):
  57.         #d(str((isDigit, s[i], i, ret)))
  58.         if not isElem:
  59.             if s[i].isdigit():
  60.                 ret += s[i]
  61.             else:
  62.                 return [isElem,ret,i]
  63.         else:
  64.             if s[i].isupper() or s[i].isdigit():
  65.                 return [isElem,ret,i]
  66.             else:
  67.                 ret += s[i]
  68.         i = i + 1
  69.     return [isElem,ret,i]
  70.  
  71. def tokenize(s):
  72.     l = list()
  73.     i = 0
  74.     while i < len(s):
  75.         newi = getWord(s, i)
  76.         i = newi[2]
  77.         l.append(newi)
  78.     return l
  79.  
  80. def standardize(tokens): # inserts implicit subscripts and puts them into ints
  81.     if tokens[0][0]:
  82.         tokens.insert(0,[False,1,0])
  83.     i = 0
  84.     while i < len(tokens):
  85.         if tokens[i][0]: # if this is an element
  86.             if i+1 == len(tokens):
  87.                 tokens.append([False,1,tokens[i][2]])
  88.             elif tokens[i+1][0]: # if the next is also an element (ie not a subscript)
  89.                 tokens.insert(i+1,[False,1,tokens[i][2]])
  90.         else: # if this was a subscript
  91.             tokens[i][1] = int(tokens[i][1])
  92.         i = i + 1
  93.    
  94.     return tokens
  95.  
  96. def molecularize(tokens):
  97.     mol = Molecule()
  98.     mol.count = tokens[0][1]
  99.     for i in range(1,len(tokens),2):
  100.         mol.add(tokens[i][1], tokens[i+1][1])
  101.     return mol
  102.  
  103. def pl(l):
  104.     for n in l:
  105.         d(n)
  106.  
  107. def getmol(s): # returns a Molecule from a string
  108.     tok = tokenize(s)
  109.     standardize(tok)
  110.     mol = molecularize(tok)
  111.     return mol
  112.  
  113. def fission(s): # splits a string 'A=B' up into molecular components [[A1,A2,...],[B1,B2,...]
  114.     lnr = s.split('=')
  115.     if len(lnr) != 2:
  116.         print 'error'
  117.         return Nothing
  118.     left = lnr[0].split('+')
  119.     right = lnr[1].split('+')
  120.    
  121.     lmols = list()
  122.     for m in left:
  123.         lmols.append(getmol(m))
  124.    
  125.     rmols = list()
  126.     for m in right:
  127.         rmols.append(getmol(m))
  128.    
  129.     return [lmols,rmols]
  130.  
  131. def fusion(lnr): # takes the output of fission and folds them for balancing
  132.     if len(lnr) != 2:
  133.         print 'error'
  134.         return Nothing
  135.    
  136.     for side in lnr:
  137.         for i in range(1,len(side)):
  138.             side[0].fold(side[i])
  139.    
  140.     return [lnr[0][0], lnr[1][0]]
  141.    
  142. def balance(s):
  143.     # split up the string into lists of left and right molecules
  144.     # add the sides together element-wise, taking coefficients into consideration
  145.     f = fusion(fission(s))
  146.    
  147.     # get element totals
  148.     l = f[0].getElementTotals()
  149.     r = f[1].getElementTotals()
  150.    
  151.     if l == r:
  152.         print "{} balances".format(s)
  153.     else:
  154.         print "{} does not balance".format(s)
  155.  
  156. def Problem3(s):
  157.     map(balance, s.split())
  158.  
  159. Problem3("6H2O+6CO2=6O2+C6H12O6 2Na+2H2O=2NaOH+H2 C6H12O6=3C2H2+3O")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement