Елена обнови решението на 10.11.2012 11:23 (преди почти 13 години)
+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
