Виктория обнови решението на 12.11.2012 17:10 (преди около 12 години)
+class Expr
+
+ include Math
+
+ def self.build(array)
+ return Unary.build(array[1], array[0]) if array.size == 2
+ return Binary.build(array[1], array[2], array[0]) if array.size == 3
+ end
+
+ def +(other)
+ Addition.new(self, other, :+)
+ end
+
+ def *(other)
+ Multiplication.new(self, other, :*)
+ end
+
+ def -@
+ Negation.new(self, :-)
+ end
+
+end
+
+class Unary < Expr
+
+ attr_accessor :expression, :operation
+
+ def initialize(expression, operation)
+ @expression, @operation = expression, operation
+ end
+
+ def self.build(expression_array, operation)
+ return Number.new(expression_array, :number) if operation == :number
+ return Variable.new(expression_array, :variable) if operation == :variable # SWITCH
+ return Sine.build(expression_array, operation) if operation == :sin
+ return Cosine.build(expression_array, operation) if operation == :cos
+ return Negation.build(expression_array, operation) if operation == :-
+ end
+
+ def ==(other)
+ operation == other.operation and expression == other.expression
+ end
+
+end
+
+class Binary < Expr
+
+ attr_accessor :left, :right, :operation
+
+ def self.build(left_array, right_array, operation)
+ return Addition.build(left_array, right_array, operation) if operation == :+
+ return Multiplication.build(left_array, right_array, operation) if operation == :*
+ end
+
+ def initialize(left, right, operation)
+ @left, @right, @operation = left, right, operation
+ end
+
+ def ==(other)
+ operation == other.operation and left == other.left and right == other.right
+ end
+
+end
+
+class Number < Unary
+
+ def evaluate(values = {})
+ expression
+ end
+
+ def derive(variable)
+ Number.new(0, :number) ######exact?
+ end
+
+ def simplify
+ Number.new(expression, :number)
+ end
+
+ def exact?
+ true
+ end
+
+end
+
+class Addition < Binary
+
+ def self.build(left_array, right_array, operation)
+ Addition.new(Expr.build(left_array), Expr.build(right_array), :+)
+ end
+
+ def evaluate(values = {})
+ left.evaluate(values) + right.evaluate(values)
+ end
+
+ def derive(variable)
+ (left.derive(variable) + right.derive(variable)).simplify
+ end
+
+ def simplify
+ return Number.new(evaluate, :number) if exact?
+ null = Number.new(0, :number)
+ if(left == null or left.simplify == null)
+ right.simplify
+ elsif(right == null or right.simplify == null)
+ left.simplify
+ else
+ Addition.new(left.simplify, right.simplify, :+)
+ end
+ end
+
+ def exact?
+ left.exact? and right.exact?
+ end
+
+end
+
+class Multiplication < Binary
+
+ def self.build(left_array, right_array, operation)
+ Multiplication.new(Expr.build(left_array), Expr.build(right_array), :*)
+ end
+
+ def evaluate(values = {})
+ left.evaluate(values) * right.evaluate(values)
+ end
+
+ def derive(variable)
+ (left.derive(variable) * right + left * right.derive(variable)).simplify
+ end
+
+ def simplify
+ return Number.new(evaluate, :number) if exact?
+ null = Number.new(0, :number)
+ if(left == null or right == null or left.simplify == null or right.simplify == null)
+ null
+ elsif(left == Number.new(1, :number) or left.simplify == Number.new(1, :number))
+ right.simplify
+ elsif(right == Number.new(1, :number) or right.simplify == Number.new(1, :number))
+ left.simplify
+ else
+ Multiplication.new(left.simplify, right.simplify, :*)
+ end
+ end
+
+ def exact?
+ left.exact? and right.exact?
+ end
+
+end
+
+class Variable < Unary
+
+ def evaluate(values = {})
+ raise ArgumentError, 'There is missing argument' unless values.keys.include? expression
+ values[expression]
+ end
+
+ def derive(dif_expression)
+ dif_expression == expression ? Number.new(1, :number) : Number.new(0, :number)
+ end
+
+ def simplify
+ Variable.new(expression, :variable)
+ end
+
+ def exact?
+ false
+ end
+
+end
+
+class Negation < Unary
+
+ def self.build(expression, operation)
+ Negation.new(Expr.build(expression), :-)
+ end
+
+ def evaluate(values = {})
+ -expression.evaluate(values)
+ end
+
+ def derive(variable)
+ -expression.derive(variable)
+ end
+
+ def simplify
+ return Number.new(evaluate, :number) if exact?
+ -expression.simplify
+ end
+
+ def exact?
+ expression.exact?
+ end
+
+end
+
+class Sine < Unary
+
+ def self.build(expression_array, operation)
+ Sine.new(Expr.build(expression_array), :sin)
+ end
+
+ def evaluate(values = {})
+ sin(expression.evaluate(values))
+ end
+
+ def derive(variable)
+ expression.derive(variable) * Cosine.new(expression, :cos)
+ end
+
+ def simplify
+ return Number.new(evaluate, :number) if exact?
+ null = Expr.build([:number, 0])
+ return null if(expression == null or expression.simplify == null)
+ Sine.new(expression.simplify, :sin)
+ end
+
+ def exact?
+ expression.exact?
+ end
+
+end
+
+class Cosine < Unary
+
+ def self.build(expression_array, operation)
+ Cosine.new(Expr.build(expression_array), :cos)
+ end
+
+ def evaluate(values = {})
+ cos(expression.evaluate(values))
+ end
+
+ def derive(variable)
+ expression.derive(variable) * (- Sine.new(expression, :sin))
+ end
+
+ def simplify
+ return Number.new(evaluate, :number) if exact?
+ Cosine.new(expression.simplify, :cos)
+ end
+
+ def exact?
+ expression.exact?
+ end
+
+end