Свилен обнови решението на 13.11.2012 23:10 (преди около 12 години)
+class Expr
+ attr_accessor :expr, :map
+
+ def initialize expr
+ @map = Hash.new()
+ @expr = expr
+ end
+
+ def == left
+ left.expr & self.expr == left.expr &&
+ left.expr & self.expr == self.expr
+ end
+
+ def Expr.build expr
+ Expr.new expr
+ end
+
+ def calculate cast
+ cast[1] = calculate cast[1] if cast[1].kind_of?(Array) == true
+ cast[2] = calculate cast[2] if cast[2].kind_of?(Array) == true
+ return variable.call( cast[1]) if cast[0] == :variable
+ return cast[1] if cast[0] == :number
+ return Calculate.clean cast
+ end
+
+ def evaluate (environment = {})
+ environment.each_pair{ |key,value| @map[key] = value }
+ calculate @expr
+ end
+
+ def variable
+ lambda{ |number| map[number] }
+ end
+
+ def cleansimlify ( cast)
+ cast[1] = cleansimlify cast[1] if cast[1].kind_of?(Array) == true
+ cast[2] = cleansimlify cast[2] if cast[2].kind_of?(Array) == true
+ Calculate.calc cast
+ return cast[1] if cast[2] == 1 && cast[0] == :*
+ return cast[2] if cast[1] == 1 && cast[0] == :*
+ return [:number, 0] if (cast[2] == 0 || cast[1] == 0 ) && cast[0] == :*
+
+ return Expr.new cast[1] if cast[2] == 0 && cast[0] == :+
+ return Expr.new cast[2] if cast[1] == 0 && cast[0] == :+
+ return cast if cast[0] == :variable
+ return cast[1] if cast[0] == :number
+ end
+
+ def Expr.variables? left, right
+ left[0] != :variables || right[0] != :variables
+ end
+
+ def Expr.variable? left
+ left[0] != :variables
+ end
+
+ def simplify
+ cleansimlify expr
+ @expr = @expr[1] if (@expr[2] == 1 || @expr[2] == [:number, 1]) && @expr[0] == :*
+ @expr = @expr[2] if (@expr[1] == 1 || @expr[1] == [:number, 1]) && @expr[0] == :*
+ @expr = [:number, 0] if (@expr[2] == 0 || @expr[1]==0 ||
+ @expr[1]==[:number,0] || @expr[2]==[:number,0]) && @expr[0] == :*
+ @expr = @expr[2] if (@expr[1] == 0 || @expr[1]==0) && @expr[0] == :+
+ @expr = @expr[1] if (@expr[2] == 0 || @expr[2]==[:number,0]) && @expr[0] == :+
+ Expr.new @expr
+ end
+end
+
+class Calculate
+
+ def Calculate.clean cast
+ case cast[0]
+ when :+
+ return Calculate.sum.call(cast[1], cast[2])
+ when :-
+ return Calculate.minus.call(cast[1])
+ when :*
+ return Calculate.multiple.call(cast[1], cast[2])
+ when :sin
+ return Calculate.sinus.call(cast[1])
+ when :cos
+ return Calculate.cos.call(cast[1])
+ end
+ end
+
+ def Calculate.calc cast
+ return Calculate.minus.call(cast[1]) if cast[0] == :- &&
+ !Expr.variables?( cast[1], cast[2] )
+ return Calculate.sum.call(cast[1], cast[2]) if cast[0] == :+ &&
+ !Expr.variables?( cast[1], cast[2] )
+ return Calculate.multiple.call(cast[1], cast[2]) if cast[0] == :* &&
+ !Expr.variables?( cast[1], cast[2] )
+ return Calculate.sinus.call(cast[1]) if cast[0] == :sin && !Expr.variable?( cast[1] )
+ return Calculate.cos.call(cast[1]) if cast[0] == :cos
+ end
+
+ def Calculate.sum
+ lambda{ |left, right| left + right }
+ end
+
+ def Calculate.multiple
+ lambda{ |left, right| left * right}
+ end
+
+
+ def Calculate.number
+ lambda{ |number| number }
+ end
+
+ def Calculate.sinus
+ lambda{ |number| Math.sin(number) }
+ end
+
+ def Calculate.minus
+ lambda{ |number| -1 * number }
+ end
+
+ def Calculate.cos
+ lambda{ |number| Math.cos(number) }
+ end
+
+end