Румен обнови решението на 14.11.2012 03:59 (преди около 12 години)
+class Expr
+ def Expr.build(ast)
+ if ast.is_a?(Array) == false then ast
+ elsif ast[0] == :number then Number.new(ast[1])
+ elsif ast[0] == :variable then Variable.new(ast[1])
+ elsif ast[0] == :+ then Addition.new(ast[1], ast[2])
+ elsif ast[0] == :* then Multiplication.new(ast[1], ast[2])
+ elsif ast[0] == :- then Negation.new(ast[1])
+ elsif ast[0] == :sin then Sine.new(ast[1])
+ elsif ast[0] == :cos then Cosine.new(ast[1])
+ else nil
+ end
+ end
+end
+
+class Unary < Expr
+ def initialize(value)
+ @value = Expr.build(value)
+ end
+
+ def exact?
+ @value.exact?
+ end
+
+ def ==(other)
+ @value == other
+ end
+end
+
+class Binary < Expr
+ def initialize(left, right)
+ @left = Expr.build(left)
+ @right = Expr.build(right)
+ end
+
+ def exact?
+ @left.exact? and @right.exact?
+ end
+
+ def ==(other)
+ @left == other.left and @right == other.right
+ end
+end
+
+class Addition < Binary
+ def evaluate(environment = {})
+ @left.evaluate(environment) + @right.evaluate(environment)
+ end
+
+ def simplify
+ if exact? then evaluate
+ elsif @left.exact? then Addition.new(@left.evaluate, @right)
+ elsif @right.exact? then Addition.new(@left, @right.evaluate)
+ else Addition.new(@left, @right)
+ end
+ end
+
+ def derive(variable)
+ addition = Addition.new(@left.derive(variable), @right.derive(variable))
+ addition.simplify
+ end
+end
+
+class Multiplication < Binary
+ def evaluate(environment = {})
+ @left.evaluate(environment) * @right.evaluate(environment)
+ end
+
+ def simplify
+ if exact? then evaluate
+ elsif @left.exact? then Multiplication.new(@left.evaluate, @right)
+ elsif @right.exact? then Multiplication.new(@left, @right.evaluate)
+ else Multiplication.new(@left, @right)
+ end
+ end
+
+ def derive(variable)
+ mult1 = Multiplication.new(@left.derive(variable), @right)
+ mult2 = Multiplication.new(@left, @right.derive(variable))
+ addition = Addition.new(mult1, mult2)
+ addition.simplify
+ end
+end
+
+class Number < Unary
+ def evaluate(environment = {})
+ @value
+ end
+
+ def exact?
+ true
+ end
+
+ def simplify
+ evaluate
+ end
+
+ def derive(variable)
+ Number.new(0)
+ end
+end
+
+class Sine < Unary
+ def evaluate(environment = {})
+ Math.sin(@value.evaluate(environment))
+ end
+
+ def simplify
+ if exact? then evaluate
+ else Sine.new(@value)
+ end
+ end
+
+ def derive(variable)
+ Multiplication.new(@value.derive(variable), Cosine.new(@value)).simplify
+ end
+end
+
+class Cosine < Unary
+ def evaluate(environment = {})
+ Math.cos(@value.evaluate(environment))
+ end
+
+ def simplify
+ if exact? then evaluate
+ else Cosine.new(@value)
+ end
+ end
+
+ def derive(variable)
+ Multiplication.new(@value.derive(variable), Negation.new(Sine.new(@value))).simplify
+ end
+end
+
+class Negation < Unary
+ def evaluate(environment = {})
+ -1 * @value.evaluate(environment)
+ end
+
+ def simplify
+ if exact? then evaluate
+ else Negation.new(@value)
+ end
+ end
+
+ def derive(variable)
+ Negation.new(@value.derive)
+ end
+end
+
+class Variable < Unary
+ def evaluate(environment = {})
+ if environment.key?(@value) then environment[@value]
+ else @value
+ end
+ end
+
+ def exact?
+ false
+ end
+
+ def simplify
+ Variable.new(@value)
+ end
+
+ def derive(variable)
+ if @value == variable then Number.new(1)
+ else Number.new(0)
+ end
+ end
+end