Чанита обнови решението на 13.11.2012 15:07 (преди около 12 години)
+class Expr
+ include Math
+
+ attr_accessor :expresion
+
+ def initialize(array = [])
+ @expresion = array
+ end
+
+ def Expr.build(array)
+ Expr.new(array)
+ end
+
+ def ==(other)
+ expresion == other.expresion
+ end
+
+ def evaluate(envirnoment = {})
+ case expresion[0]
+ when :- then Negation.new(expresion).evaluate(envirnoment)
+ when :sin then Sine.new(expresion).evaluate(envirnoment)
+ when :cos then Cosine.new(expresion).evaluate(envirnoment)
+ when :variable then Variable.new(expresion).evaluate(envirnoment)
+ when :number then Number.new(expresion).evaluate(envirnoment)
+ when :+ then Addition.new(expresion).evaluate(envirnoment)
+ when :* then Multiplication.new(expresion).evaluate(envirnoment)
+ end
+ end
+
+ def simplify
+ case expresion[0]
+ when :- then Negation.new(expresion).simplify
+ when :sin then Sine.new(expresion).simplify
+ when :cos then Cosine.new(expresion).simplify
+ when :variable then Variable.new(expresion).simplify
+ when :number then Number.new(expresion).simplify
+ when :+ then Addition.new(expresion).simplify
+ when :* then Multiplication.new(expresion).simplify
+ end
+ end
+
+ def derive(variable)
+ case expresion[0]
+ when :- then Negation.new(expresion).derive(variable).simplify
+ when :sin then Sine.new(expresion).derive(variable).simplify
+ when :cos then Cosine.new(expresion).derive(variable).simplify
+ when :variable then Variable.new(expresion).derive(variable).simplify
+ when :number then Number.new(expresion).derive(variable).simplify
+ when :+ then Addition.new(expresion).derive(variable).simplify
+ when :* then Multiplication.new(expresion).derive(variable).simplify
+ end
+ end
+
+ def exact?
+ return true if(expresion.flatten.include?(:variable))
+ false
+ end
+end
+
+class Number < Expr
+ attr_accessor :number
+
+ def evaluate(envirnoment={})
+ expresion[1]
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ Expr.new([:number, 0])
+ end
+end
+
+class Addition < Expr
+
+ attr_accessor :left_expresion , :right_expresion
+
+ def initialize(array)
+ super
+ @left_expresion = Expr.new(expresion[1])
+ @right_expresion = Expr.new(expresion[2])
+ end
+
+ def evaluate(envirnoment={})
+ left_expresion.evaluate(envirnoment) + right_expresion.evaluate(envirnoment)
+ end
+
+ def simplify
+ return right_expresion.simplify if(left_expresion.simplify.expresion == [:number, 0])
+ return left_expresion.simplify if(right_expresion.simplify.expresion == [:number, 0])
+ Expr.new([:+, left_expresion.simplify.expresion, right_expresion.simplify.expresion])
+ end
+
+ def derive(variable)
+ result = Expr.new([:+, left_expresion.derive(variable).expresion,
+ right_expresion.derive(variable).expresion])
+ return Expr.new([:number, result.evaluate]) if(!(result.exact?))
+ result
+ end
+end
+
+class Multiplication < Expr
+
+ attr_accessor :left_expresion, :right_expresion
+
+ def initialize(array)
+ super
+ @left_expresion = Expr.new(expresion[1])
+ @right_expresion = Expr.new(expresion[2])
+ end
+
+ def evaluate(envirnoment={})
+ left_expresion.evaluate(envirnoment) * right_expresion.evaluate(envirnoment)
+ end
+
+ def simplify
+ return right_expresion.simplify if(left_expresion.simplify.expresion == [:number, 1])
+ return left_expresion.simplify if(right_expresion.simplify.expresion == [:number, 1])
+ return Expr.new([:number, 0]) if(left_expresion.simplify.expresion == [:number, 0])
+ return Expr.new([:number, 0]) if(right_expresion.simplify.expresion == [:number, 0])
+ Expr.new([:*, left_expresion.simplify.expresion, right_expresion.simplify.expresion])
+ end
+
+ def derive(variable)
+ result = Expr.new([:+,
+ [:*, left_expresion.derive(variable).expresion, right_expresion.expresion],
+ [:*, left_expresion.expresion,right_expresion.derive(variable).expresion]])
+ return Expr.new([:number, result.evaluate]) if(!(result.exact?))
+ result
+ end
+end
+
+class Variable < Expr
+
+ attr_accessor :variable
+
+ def evaluate(envirnoment = {})
+ Number.new([:number,envirnoment.fetch(expresion[1])]).evaluate(envirnoment)
+ end
+
+ def simplify
+ Expr.new([:variable, expresion[1]])
+ end
+
+ def derive(derive_variable)
+ return Expr.new([:number, 1]) if(expresion[1] == derive_variable)
+ Expr.new([:number, 0])
+ end
+
+end
+
+class Negation < Expr
+
+ attr_accessor :expresion
+
+ def initialize(array)
+ @expresion = array[1]
+ end
+
+ def evaluate(envirnoment={})
+ result = 0
+ result -= super
+ result
+ end
+
+ def simplify
+ return Expr.new([:number, 0]) if(super.expresion == [:number, 0])
+ return Expr.new([:-, [:number, 1]]) if(super.expresion == [:number, 1])
+ Expr.new([:-, super.expresion])
+ end
+
+ def derive(variable)
+ result = Expr.new([:-, super.expresion])
+ return Expr.new([:number, result.evaluate]) if(!(result.exact?))
+ result
+ end
+end
+
+class Sine < Expr
+
+ attr_accessor :expresion
+
+ def initialize(array)
+ @expresion = array[1]
+ end
+
+ def evaluate(envirnoment={})
+ sin(super)
+ end
+
+ def simplify
+ return Expr.new([:number, 0]) if(super.expresion == [:number, 0])
+ return Expr.new([:sin, [:number, 1]]) if(super.expresion == [:number, 1])
+ Expr.new([:sin, super.expresion])
+ end
+
+ def derive(variable)
+ result = Expr.new([:*, super.expresion, [:cos, expresion]])
+ return Expr.new([:number, result.evaluate]) if(!(result.exact?))
+ result
+ end
+end
+
+class Cosine < Expr
+
+ attr_accessor :expresion
+
+ def initialize(array)
+ @expresion = array[1]
+ end
+
+ def evaluate(envirnoment={})
+ cos(super)
+ end
+
+ def simplify
+ return Expr.new([:number, 1]) if(super.expresion == [:number, 0])
+ return Expr.new([:cos, [:number, 1]]) if(super.expresion == [:number, 1])
+ Expr.new([:cos, super.expresion])
+ end
+
+ def derive(variable)
+ result = Expr.new([:*, super.expresion, [:-, [:cos, expresion]]])
+ return Expr.new([:number, result.evaluate]) if(!(result.exact?))
+ result
+ end
+end