Иван обнови решението на 12.11.2012 17:42 (преди около 12 години)
+class Expr
+ def self.build(expression)
+ if expression[0] == :+ or expression[0] == :* then Binary.build(expression)
+ else Unary.build(expression)
+ end
+ end
+end
+
+class Unary < Expr
+ def self.build(expression)
+ if expression[0] == :number then (Number.new(expression[1])).simplify
+ elsif expression[0] == :variable then (Variable.new(expression[1])).simplify
+ elsif expression[0] == :- then (Negation.new(Expr.build(expression[1]))).simplify
+ elsif expression[0] == :sin then (Sine.new(Expr.build(expression[1]))).simplify
+ else (Cosine.new(Expr.build(expression[1]))).simplify
+ end
+ end
+end
+
+class Binary < Expr
+ def self.build(expression)
+ if expression[0] == :+
+ (Addition.new(Expr.build(expression[1]), Expr.build(expression[2]))).simplify
+ else (Multiplication.new(Expr.build(expression[1]), Expr.build(expression[2]))).simplify
+ end
+ end
+end
+
+class Number < Unary
+ attr_accessor :operand
+
+ def initialize(operand)
+ @operand = operand
+ end
+
+ def derive(variable)
+ Number.new(0)
+ end
+
+ def ==(other_number)
+ if not other_number.instance_of? Number then return false
+ end
+ operand == other_number.operand
+ end
+
+ def evaluate(environment = {})
+ operand
+ end
+
+ def exact?
+ false
+ end
+
+ def simplify
+ self
+ end
+end
+
+class Addition < Binary
+ attr_accessor :operand1, :operand2
+
+ def initialize(operand1, operand2)
+ @operand1 = operand1
+ @operand2 = operand2
+ end
+
+ def derive(variable)
+ (Addition.new(operand1.derive(variable), operand2.derive(variable))).simplify
+ end
+
+ def ==(other_addition)
+ if not other_addition.instance_of? Addition then return false
+ end
+ operand1 == other_addition.operand1 and operand2 == other_addition.operand2
+ end
+
+ def evaluate(environment = {})
+ operand1.evaluate(environment) + operand2.evaluate(environment)
+ end
+
+ def exact?
+ operand1.exact? or operand2.exact?
+ end
+
+ def simplify
+ if not operand1.exact? and not operand2.exact?
+ return Number.new(operand1.evaluate + operand2.evaluate)
+ end
+ if not operand1.exact? and operand1.evaluate == 0 then return operand2.simplify
+ end
+ if not operand2.exact? and operand2.evaluate == 0 then return operand1.simplify
+ end
+ expression = Addition.new(operand1.simplify, operand2.simplify)
+ end
+end
+
+
+class Multiplication < Binary
+ attr_accessor :operand1, :operand2
+
+ def initialize(operand1, operand2)
+ @operand1 = operand1
+ @operand2 = operand2
+ end
+
+ def derive(variable)
+ (Addition.new Multiplication.new(operand1.derive(variable), operand2),
+ Multiplication.new(operand1, operand2.derive(variable))).simplify
+ end
+
+ def ==(other_multiplication)
+ if not other_multiplication.instance_of? Multiplication then return false
+ end
+ operand1 == other_multiplication.operand1 and operand2 == other_multiplication.operand2
+ end
+
+ def evaluate(environment = {})
+ operand1.evaluate(environment) * operand2.evaluate(environment)
+ end
+
+ def exact?
+ operand1.exact? or operand2.exact?
+ end
+
+ def simplify
+ if not operand1.exact? and not @operand2.exact?
+ return Number.new(operand1.evaluate * operand2.evaluate)
+ end
+ if not operand1.exact? and operand1.evaluate == 1 then return operand2.simplify
+ end
+ if not operand2.exact? and operand2.evaluate == 1 then return operand1.simplify
+ end
+ if not operand1.exact? and operand1.evaluate == 0 then return Number.new(0)
+ end
+ if not operand2.exact? and operand2.evaluate == 0 then return Number.new(0)
+ end
+ expression = Multiplication.new(operand1.simplify, operand2.simplify)
+ end
+end
+
+class Variable < Unary
+ attr_accessor :operand
+
+ def initialize(operand)
+ @operand = operand
+ end
+
+ def derive(variable)
+ if operand == variable then Number.new(1)
+ else Number.new(0)
+ end
+ end
+
+ def ==(other_variable)
+ if not other_variable.instance_of? Variable then return false
+ end
+ operand == other_variable.operand
+ end
+
+ def evaluate(environment = {})
+ environment.each { |key, value| if key == operand then return value end }
+ puts "There are no such variables in the expression or not enough arguments are given!"
+ exit
+ end
+
+ def exact?
+ true
+ end
+
+ def simplify
+ self
+ end
+end
+
+class Negation < Unary
+ attr_accessor :operand
+
+ def initialize(operand)
+ @operand = operand
+ end
+
+ def derive(variable)
+ (Multiplication.new(Number.new(-1), operand.derive(variable))).simplify
+ end
+
+ def ==(other_negation)
+ if not other_negation.instance_of? Negation then return false
+ end
+ operand == other_negation.operand
+ end
+
+ def evaluate(environment = {})
+ if operand.instance_of? Number then return -@operand.operand
+ end
+ environment.each { |key, value| if key == @operand.operand then return -value end }
+ end
+
+ def exact?
+ operand.exact?
+ end
+
+ def simplify
+ Negation.new(operand.simplify)
+ end
+end
+
+class Sine < Unary
+ include Math
+
+ attr_accessor :operand
+
+ def initialize(operand)
+ @operand = operand
+ end
+
+ def derive(variable)
+ (Multiplication.new(operand.derive(variable), Cosine.new(operand))).simplify
+ end
+
+ def ==(other_sine)
+ if not other_sine.instance_of? Sine then return false
+ end
+ operand == other_sine.operand
+ end
+
+ def evaluate(environment = {})
+ if operand.instance_of? Number then return sin(@operand.operand)
+ end
+ environment.each { |key, value| if key == @operand.operand then return sin(value) end }
+ end
+
+ def exact?
+ operand.exact?
+ end
+
+ def simplify
+ if not operand.exact? and operand.evaluate == 0 then return Number.new(0)
+ end
+ Sine.new(operand.simplify)
+ end
+end
+
+class Cosine < Unary
+ include Math
+
+ attr_accessor :operand
+
+ def initialize(operand)
+ @operand = operand
+ end
+
+ def derive(variable)
+ Multiplication.new(operand.derive(variable), Negation.new(Sine.new(operand)))
+ end
+
+ def ==(other_cosine)
+ if not other_cosine.instance_of? Cosine then return false
+ end
+ operand == other_cosine.operand
+ end
+
+ def evaluate(environment = {})
+ if operand.instance_of? Number then return cos(@operand.operand)
+ end
+ environment.each { |key, value| if key == operand.operand then return cos(value) end }
+ end
+
+ def exact?
+ operand.exact?
+ end
+
+ def simplify
+ Cosine.new(operand.simplify)
+ end
+end