Class: RubyChem::Equation
- Inherits:
-
Object
- Object
- RubyChem::Equation
- Defined in:
- lib/rubychem/equation.rb
Instance Attribute Summary collapse
-
#array ⇒ Object
Returns the value of attribute array.
-
#balanced ⇒ Object
Returns the value of attribute balanced.
-
#left ⇒ Object
Returns the value of attribute left.
-
#left_system_of_equations ⇒ Object
Returns the value of attribute left_system_of_equations.
-
#left_total ⇒ Object
Returns the value of attribute left_total.
-
#right ⇒ Object
Returns the value of attribute right.
-
#right_system_of_equations ⇒ Object
Returns the value of attribute right_system_of_equations.
-
#right_total ⇒ Object
Returns the value of attribute right_total.
-
#search_order ⇒ Object
Returns the value of attribute search_order.
Instance Method Summary collapse
-
#apply_solved_equivalent_fractions_to_fraction ⇒ Object
Now that we have the whole number from solve_equivalent_fractions we must apply that to each of the fractions to solve for the balanced equation.
- #assign_coeficients_to_part_system_of_equations(part, atom_to_search) ⇒ Object
-
#assign_coeficients_to_system_of_equations ⇒ Object
2.
- #balance ⇒ Object
- #balanced_string ⇒ Object
-
#convert_to(ary, type) ⇒ Object
type should be one of :to_s, :to_i, :to_f, :to_r.
- #convert_to_rational(ary) ⇒ Object
-
#initialize(equation) ⇒ Equation
constructor
Checks if two formulas are balanced.
- #instantiate_chemical_object_from_string(equation, side) ⇒ Object
- #is_balanced? ⇒ Boolean
-
#list_atoms ⇒ Object
add up all atoms, on each side left = Na:1,Cl:2 right = Na:2,Cl:4.
- #list_part(part, total) ⇒ Object
- #part_set_up_system_of_equations(part, total) ⇒ Object
- #print_matrix(m) ⇒ Object
- #process_equation_string(left_and_right) ⇒ Object
-
#reduced_row_echelon_form(ary) ⇒ Object
returns an 2-D array where each element is a Rational.
-
#set_up_system_of_equations ⇒ Object
System of Equations setup 1.
-
#solve_equivalent_fractions ⇒ Object
from the reduced row echelon form we are left with a set of equivalent fractions to transform into a whole number we do this by using the gcdlcm method.
- #subtract_right_side ⇒ Object
-
#write_matrix ⇒ Object
3.
Constructor Details
#initialize(equation) ⇒ Equation
Checks if two formulas are balanced. Takes user input.. such as x + y + z = a + b yields @left[Chemical1, Chemical2, Chemical3], @right
10 11 12 13 14 15 16 |
# File 'lib/rubychem/equation.rb', line 10 def initialize(equation) @left = Array.new @right = Array.new left_and_right = equation.split(/\=/) process_equation_string(left_and_right) end |
Instance Attribute Details
#array ⇒ Object
Returns the value of attribute array.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def array @array end |
#balanced ⇒ Object
Returns the value of attribute balanced.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def balanced @balanced end |
#left ⇒ Object
Returns the value of attribute left.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def left @left end |
#left_system_of_equations ⇒ Object
Returns the value of attribute left_system_of_equations.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def left_system_of_equations @left_system_of_equations end |
#left_total ⇒ Object
Returns the value of attribute left_total.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def left_total @left_total end |
#right ⇒ Object
Returns the value of attribute right.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def right @right end |
#right_system_of_equations ⇒ Object
Returns the value of attribute right_system_of_equations.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def right_system_of_equations @right_system_of_equations end |
#right_total ⇒ Object
Returns the value of attribute right_total.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def right_total @right_total end |
#search_order ⇒ Object
Returns the value of attribute search_order.
4 5 6 |
# File 'lib/rubychem/equation.rb', line 4 def search_order @search_order end |
Instance Method Details
#apply_solved_equivalent_fractions_to_fraction ⇒ Object
Now that we have the whole number from solve_equivalent_fractions we must apply that to each of the fractions to solve for the balanced equation
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/rubychem/equation.rb', line 172 def apply_solved_equivalent_fractions_to_fraction int = self.solve_equivalent_fractions answer = [] @reduced_row_echelon_form.each do |row| answer << row.last * int end answer << int count = 0 @balanced = Hash.new @left_system_of_equations.each do |x,v| answer[count] @left_system_of_equations[x] = answer[count].to_i.abs unless answer[count].nil? count += 1 end @right_system_of_equations.each do |x,v| answer[count] @right_system_of_equations[x] = answer[count].to_i.abs unless answer[count].nil? count += 1 end answer @balanced = {left:@left_system_of_equations,right:@right_system_of_equations} self.balanced_string end |
#assign_coeficients_to_part_system_of_equations(part, atom_to_search) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/rubychem/equation.rb', line 108 def assign_coeficients_to_part_system_of_equations(part,atom_to_search) chemicals = part.keys chemicals.each do |chemical| @search_order << chemical # look at the Chemical chemical.chem_species.each do |atom| # Does the chemical have the atom we are looking for? if atom_to_search == atom[0] part[chemical] = atom[1] end end end end |
#assign_coeficients_to_system_of_equations ⇒ Object
-
determnie instances on left and right of each atom, and assign those to coeficients
C12H26 + O2 = CO2 + H2O O = + 1dā O = ā2b=2c+1dā
94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubychem/equation.rb', line 94 def assign_coeficients_to_system_of_equations self.list_atoms atom_list = self.left_total.merge(self.right_total) # Get the Chemical list atom_list.keys.each do |atom| self.set_up_system_of_equations assign_coeficients_to_part_system_of_equations(@right_system_of_equations,atom) assign_coeficients_to_part_system_of_equations(@left_system_of_equations,atom) subtract_right_side write_matrix end end |
#balance ⇒ Object
145 146 147 148 149 150 151 152 |
# File 'lib/rubychem/equation.rb', line 145 def balance @search_order = Array.new @array = Array.new @reduced_row_echelon_form = Array.new self.assign_coeficients_to_system_of_equations @reduced_row_echelon_form = self.reduced_row_echelon_form(@array) self.apply_solved_equivalent_fractions_to_fraction end |
#balanced_string ⇒ Object
196 197 198 199 200 201 202 203 204 |
# File 'lib/rubychem/equation.rb', line 196 def balanced_string array_of_strings = Array.new @balanced[:left].each{|x,y|array_of_strings << (x.chem_species.unshift(y).join);x.chem_species.shift} left = array_of_strings.join(" + ") array_of_strings = [] @balanced[:right].each{|x,y|array_of_strings << (x.chem_species.unshift(y).join);x.chem_species.shift} right = array_of_strings.join(" + ") left + " = " + right end |
#convert_to(ary, type) ⇒ Object
type should be one of :to_s, :to_i, :to_f, :to_r
250 251 252 253 254 255 256 |
# File 'lib/rubychem/equation.rb', line 250 def convert_to(ary, type) new = [] ary.each_index do |row| new << ary[row].collect {|elem| elem.send(type)} end new end |
#convert_to_rational(ary) ⇒ Object
241 242 243 244 245 246 247 |
# File 'lib/rubychem/equation.rb', line 241 def convert_to_rational(ary) new = [] ary.each_index do |row| new << ary[row].collect {|elem| Rational(elem)} end new end |
#instantiate_chemical_object_from_string(equation, side) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/rubychem/equation.rb', line 23 def instantiate_chemical_object_from_string(equation, side) if side == "left" equation.split(/\+/).each do |chemical| @left << RubyChem::Chemical.new(chemical.strip) end else equation.split(/\+/).each do |chemical| @right << RubyChem::Chemical.new(chemical.strip) end end end |
#is_balanced? ⇒ Boolean
58 59 60 61 62 63 |
# File 'lib/rubychem/equation.rb', line 58 def is_balanced? @right_total.each_key do |key| @balanced = @right_total[key] == @left_total[key] end @balanced end |
#list_atoms ⇒ Object
add up all atoms, on each side left = Na:1,Cl:2 right = Na:2,Cl:4
39 40 41 42 43 44 |
# File 'lib/rubychem/equation.rb', line 39 def list_atoms @left_total = Hash.new @right_total = Hash.new list_part(@left, @left_total) list_part(@right, @right_total) end |
#list_part(part, total) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/rubychem/equation.rb', line 46 def list_part(part, total) part.each do |chemical| chemical.chem_species.each do |atom| if total[atom[0]].nil? total[atom[0]] = atom[1] else total[atom[0]] += atom[1] end end end end |
#part_set_up_system_of_equations(part, total) ⇒ Object
83 84 85 86 87 |
# File 'lib/rubychem/equation.rb', line 83 def part_set_up_system_of_equations(part,total) part.each do |key| total[key] = 0 end end |
#print_matrix(m) ⇒ Object
258 259 260 261 262 |
# File 'lib/rubychem/equation.rb', line 258 def print_matrix(m) max = m[0].collect {-1} m.each {|row| row.each_index {|i| max[i] = [max[i], row[i].to_s.length].max}} m.each {|row| row.each_index {|i| print "%#{max[i]}s " % row[i].to_s}; puts ""} end |
#process_equation_string(left_and_right) ⇒ Object
18 19 20 21 |
# File 'lib/rubychem/equation.rb', line 18 def process_equation_string(left_and_right) instantiate_chemical_object_from_string(left_and_right[0], "left") instantiate_chemical_object_from_string(left_and_right[1], "right") end |
#reduced_row_echelon_form(ary) ⇒ Object
returns an 2-D array where each element is a Rational
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/rubychem/equation.rb', line 207 def reduced_row_echelon_form(ary) lead = 0 rows = ary.size cols = ary[0].size rary = convert_to_rational(ary) # use rational arithmetic catch :done do rows.times do |r| throw :done if cols <= lead i = r while rary[i][lead] == 0 i += 1 if rows == i i = r lead += 1 throw :done if cols == lead end end # swap rows i and r rary[i], rary[r] = rary[r], rary[i] # normalize row r v = rary[r][lead] rary[r].collect! {|x| x /= v} # reduce other rows rows.times do |i| next if i == r v = rary[i][lead] rary[i].each_index {|j| rary[i][j] -= v * rary[r][j]} end lead += 1 end end rary end |
#set_up_system_of_equations ⇒ Object
System of Equations setup
-
Assign unknown coeficients
C12H26 + O2 = CO2 + H2O aC12H26 + bO2 = cCO2 + dH2O
76 77 78 79 80 81 |
# File 'lib/rubychem/equation.rb', line 76 def set_up_system_of_equations @right_system_of_equations = Hash.new @left_system_of_equations = Hash.new part_set_up_system_of_equations(@right,@right_system_of_equations) part_set_up_system_of_equations(@left,@left_system_of_equations) end |
#solve_equivalent_fractions ⇒ Object
from the reduced row echelon form we are left with a set of equivalent fractions to transform into a whole number we do this by using the gcdlcm method
158 159 160 161 162 163 164 165 166 |
# File 'lib/rubychem/equation.rb', line 158 def solve_equivalent_fractions last = 0 array = Array.new @reduced_row_echelon_form.each do |x| array = last.gcdlcm(x.last.denominator) last = x.last.denominator end array.max end |
#subtract_right_side ⇒ Object
122 123 124 125 126 |
# File 'lib/rubychem/equation.rb', line 122 def subtract_right_side self.right_system_of_equations.each do |k,v| self.right_system_of_equations[k] = v *= -1 end end |
#write_matrix ⇒ Object
-
Rearrange the system of equations and write it in a matrix
a b c d
O 0 2 -2 -1
- [0,2,-2,-1]
133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rubychem/equation.rb', line 133 def write_matrix array = Array.new @left_system_of_equations.keys.each do |key| array << @left_system_of_equations[key] end @right_system_of_equations.keys.each do |key| array << @right_system_of_equations[key] end @array << array end |