Елена обнови решението на 10.11.2012 11:23 (преди около 12 години)
+class Expr
+ def self.build exprTree
+ exprTree.length == 2 ? Unary.build(exprTree) : Binary.build(exprTree)
+ end
+
+ def *(other)
+ Multiplication.new(self,other)
+ end
+
+ def +(other)
+ Addition.new(self,other)
+ end
+
+ def -@
+ Negation.new(self)
+ end
+end
+
+class Unary < Expr
+ def self.build exprTree
+ case exprTree[0]
+ when :number then Number.new exprTree[1]
+ when :variable then Variable.new exprTree[1]
+ when :- then Negation.build exprTree[1]
+ when :sin then Sine.build exprTree[1]
+ when :cos then Cosine.build exprTree[1]
+ end
+ end
+
+ def == other
+ self.class == other.class &&
+ self.expr == other.expr
+ end
+end
+
+class Binary < Expr
+ def self.build exprTree
+ case exprTree[0]
+ when :+ then Addition.build exprTree[1], exprTree[2]
+ when :* then Multiplication.build exprTree[1], exprTree[2]
+ end
+ end
+
+ def == other
+ self.class == other.class &&
+ self.leftExpr == other.leftExpr &&
+ self.rightExpr == other.rightExpr
+ end
+end
+
+class Number < Unary
+ attr_accessor :expr
+
+ def initialize expr
+ @expr = expr
+ end
+
+ def evaluate environment = {}
+ expr
+ end
+
+ def exact?
+ true
+ end
+
+ def simplify
+ Number.new expr
+ end
+
+ def derive x
+ return Number.new 0
+ end
+end
+
+class Variable < Unary
+ attr_accessor :expr
+
+ def initialize expr
+ @expr = expr
+ end
+
+ def evaluate environment = {}
+ environment[expr]
+ end
+
+ def exact?
+ false
+ end
+
+ def simplify
+ Variable.new expr
+ end
+
+ def derive y
+ expr == y ? Number.new(1) : Number.new(0)
+ end
+end
+
+class Negation < Unary
+ attr_accessor :expr
+
+ def initialize expr
+ @expr = expr
+ end
+
+ def self.build exprTree
+ self.new Expr.build exprTree
+ end
+
+ def evaluate environment = {}
+ -expr.evaluate(environment)
+ end
+
+ def exact?
+ expr.exact?
+ end
+
+ def simplify
+ simplified = expr.simplify
+ simplified.exact? ? Number.new(-1 * simplified.evaluate) : -simplified
+ end
+
+ def derive y
+ (-expr.derive(y)).simplify
+ end
+end
+
+class Sine < Unary
+ attr_accessor :expr
+
+ def initialize expr
+ @expr = expr
+ end
+
+ def self.build exprTree
+ self.new Expr.build exprTree
+ end
+
+ def evaluate environment = {}
+ value = expr.evaluate(environment)
+ value ? Math.sin(value) : nil
+ end
+
+ def exact?
+ expr.exact?
+ end
+
+ def simplify
+ simplified = expr.simplify
+ simplified.exact? ? Number.new(Math.sin(simplified.evaluate)) : Sine.new(simplified)
+ end
+
+ def derive y
+ (expr.derive(y) * Cosine.new(expr)).simplify
+ end
+end
+
+class Cosine < Unary
+ attr_accessor :expr
+
+ def initialize expr
+ @expr = expr
+ end
+
+ def self.build exprTree
+ self.new(Expr.build(exprTree))
+ end
+
+ def evaluate environment = {}
+ value = expr.evaluate(environment)
+ value ? Math.cos(value) : nil
+ end
+
+ def exact?
+ expr.exact?
+ end
+
+ def simplify
+ simplified = expr.simplify
+ simplified.exact? ? Number.new(Math.cos(simplified.evaluate)) : Cosine.new(simplified)
+ end
+
+ def derive y
+ (expr.derive(y) * -Sine.new(expr)).simplify
+ end
+end
+
+class Addition < Binary
+ attr_accessor :leftExpr, :rightExpr
+
+ def initialize leftExpr, rightExpr
+ @leftExpr, @rightExpr = leftExpr, rightExpr
+ end
+
+ def self.build leftExprTree, rightExprTree
+ self.new Expr.build(leftExprTree), Expr.build(rightExprTree)
+ end
+
+ def evaluate(environment = {})
+ leftValue = leftExpr.evaluate environment
+ rightValue = rightExpr.evaluate environment
+ leftValue && rightValue ? leftValue + rightValue : nil
+ end
+
+ def exact?
+ leftExpr.exact? && rightExpr.exact?
+ end
+
+ def simplify
+ leftSimplified, rightSimplified = leftExpr.simplify,rightExpr.simplify
+ return rightSimplified if leftSimplified.exact? && leftSimplified.evaluate == 0
+ return leftSimplified if rightSimplified.exact? && rightSimplified.evaluate == 0
+ if leftSimplified.exact? && rightSimplified.exact?
+ Number.new(leftSimplified.evaluate + rightSimplified.evaluate)
+ else
+ leftSimplified + rightSimplified
+ end
+ end
+
+ def derive y
+ (leftExpr.derive(y) + rightExpr.derive(y)).simplify
+ end
+end
+
+class Multiplication < Binary
+ attr_accessor :leftExpr, :rightExpr
+
+ def initialize leftExpr, rightExpr
+ @leftExpr, @rightExpr = leftExpr, rightExpr
+ end
+
+ def self.build leftExprTree, rightExprTree
+ self.new Expr.build(leftExprTree), Expr.build(rightExprTree)
+ end
+
+ def evaluate environment = {}
+ leftValue = leftExpr.evaluate(environment)
+ rightValue = rightExpr.evaluate(environment)
+ leftValue && rightValue ? leftValue * rightValue : nil
+ end
+
+ def exact?
+ leftExpr.exact? && rightExpr.exact?
+ end
+
+ def simplify
+ leftSimplified, rightSimplified = leftExpr.simplify,rightExpr.simplify
+ if (leftSimplified.exact?)
+ return rightSimplified if leftSimplified.evaluate == 1
+ return Number.new 0 if leftSimplified.evaluate == 0
+ end
+ if (rightSimplified.exact?)
+ return leftSimplified if rightSimplified.evaluate == 1
+ return Number.new 0 if rightSimplified.evaluate == 0
+ end
+ if leftSimplified.exact? && rightSimplified.exact?
+ Number.new(leftSimplified.evaluate * rightSimplified.evaluate)
+ else
+ Multiplication.new(leftSimplified,rightSimplified)
+ end
+ end
+
+ def derive y
+ (leftExpr.derive(y) * rightExpr + leftExpr * rightExpr.derive(y)).simplify
+ end
+end