View difference between Paste ID: q19kTMRT and RfFiHBHy
SHOW: | | - or go back to the newest paste.
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-
		print n
103+
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-
	print "fission"
141+
142-
	fis = fission(s)
142+
143-
	for side in fis:
143+
	# split up the string into lists of left and right molecules
144-
		pl(side)
144+
	# add the sides together element-wise, taking coefficients into consideration
145-
	print "fusion"
145+
	f = fusion(fission(s))
146-
	fus = fusion(fis)
146+
147-
	pl(fus)
147+
	# get element totals
148
	l = f[0].getElementTotals()
149-
	l = fus[0].getElementTotals()
149+
	r = f[1].getElementTotals()
150-
	r = fus[1].getElementTotals()
150+
151
	if l == r:
152-
	return l == r
152+
		print "{} balances".format(s)
153
	else:
154-
print balance("H2O+H2O=2H2O")
154+
		print "{} does not balance".format(s)
155-
# to do the function multiple times, map(balance, input.split())
155+
156
def Problem3(s):
157
	map(balance, s.split())
158
159
Problem3("6H2O+6CO2=6O2+C6H12O6 2Na+2H2O=2NaOH+H2 C6H12O6=3C2H2+3O")