Тодор обнови решението на 14.11.2012 14:41 (преди около 12 години)
+class UndefinedVariableError < StandardError
+end
+
+class Expr
+ attr_accessor :s_expr
+
+ def initialize(s_expr)
+ @s_expr = s_expr
+ end
+
+ def self.build(s_expr)
+ new s_expr
+ end
+
+ def ==(other_expr)
+ s_expr == other_expr.s_expr
+ end
+
+ def +(other_expr)
+ Expr.build [:+, s_expr, other_expr.s_expr]
+ end
+
+ def *(other_expr)
+ Expr.build [:*, s_expr, other_expr.s_expr]
+ end
+
+ def -@
+ Expr.build [:-, s_expr]
+ end
+
+ def evaluate(environment = {})
+ case s_expr[0]
+ when :number then return Number.build(s_expr).evaluate(environment)
+ when :variable then return Variable.build(s_expr).evaluate(environment)
+ when :+ then return Addition.build(s_expr).evaluate(environment)
+ when :* then return Multiplication.build(s_expr).evaluate(environment)
+ when :- then return Negation.build(s_expr).evaluate(environment)
+ when :sin then return Sine.build(s_expr).evaluate(environment)
+ when :cos then return Cosine.build(s_expr).evaluate(environment)
+ end
+ end
+
+ def derive(variable)
+ case s_expr[0]
+ when :number then return Number.build(s_expr).derive(variable).simplify
+ when :variable then return Variable.build(s_expr).derive(variable).simplify
+ when :+ then return Addition.build(s_expr).derive(variable).simplify
+ when :* then return Multiplication.build(s_expr).derive(variable).simplify
+ when :- then return Negation.build(s_expr).derive(variable).simplify
+ when :sin then return Sine.build(s_expr).derive(variable).simplify
+ when :cos then return Cosine.build(s_expr).derive(variable).simplify
+ end
+ end
+
+ def simplify
+ case s_expr[0]
+ when :number then return Number.build(s_expr).simplify
+ when :variable then return Variable.build(s_expr).simplify
+ when :+ then return Addition.build(s_expr).simplify
+ when :* then return Multiplication.build(s_expr).simplify
+ when :- then return Negation.build(s_expr).simplify
+ when :sin then return Sine.build(s_expr).simplify
+ when :cos then return Cosine.build(s_expr).simplify
+ end
+ end
+
+end
+
+class Unary < Expr
+ def operand
+ s_expr[1]
+ end
+end
+
+class Binary < Expr
+ def operand1
+ s_expr[1]
+ end
+
+ def operand2
+ s_expr[2]
+ end
+end
+
+class Number < Unary
+ def evaluate(environment = {})
+ operand
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ Expr.build [:number, 0]
+ end
+end
+
+class Variable < Unary
+ def evaluate(environment = {})
+ if environment.has_key? operand
+ environment[operand]
+ else
+ raise UndefinedVariableError
+ end
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ if operand == variable
+ return Expr.build [:number, 1]
+ else
+ return Expr.build [:number, 0]
+ end
+ end
+end
+
+class Addition < Binary
+ def evaluate(environment = {})
+ Expr.build(operand1).evaluate(environment) + Expr.build(operand2).evaluate(environment)
+ end
+
+ def simplify
+ begin
+ return Expr.build [:number, evaluate]
+ rescue UndefinedVariableError
+ if Expr.build(operand1).simplify == Expr.build([:number, 0])
+ return Expr.build(operand2).simplify
+ elsif Expr.build(operand2).simplify == Expr.build([:number, 0])
+ return Expr.build(operand1).simplify
+ else
+ return Expr.build(operand1).simplify + Expr.build(operand2).simplify
+ end
+ end
+ end
+
+ def derive(variable)
+ Expr.build(operand1).derive(variable) + Expr.build(operand2).derive(variable)
+ end
+end
+
+class Multiplication < Binary
+ def evaluate(environment = {})
+ Expr.build(operand1).evaluate(environment) * Expr.build(operand2).evaluate(environment)
+ end
+
+ def simplify
+ begin
+ return Expr.build [:number, evaluate]
+ rescue UndefinedVariableError
+ if Expr.build(operand1).simplify == Expr.build([:number, 1])
+ return Expr.build(operand2).simplify
+ elsif Expr.build(operand2).simplify == Expr.build([:number, 1])
+ return Expr.build(operand1).simplify
+ elsif Expr.build(operand1).simplify == Expr.build([:number, 0]) or
+ Expr.build(operand2).simplify == Expr.build([:number, 0])
+ return Expr.build [:number, 0]
+ else
+ return Expr.build(operand1).simplify * Expr.build(operand2).simplify
+ end
+ end
+ end
+
+ def derive(variable)
+ Expr.build(operand1).derive(variable) * Expr.build(operand2) +
+ Expr.build(operand1) * Expr.build(operand2).derive(variable)
+ end
+end
+
+class Negation < Unary
+ def evaluate(environment = {})
+ - Expr.build(operand).evaluate(environment)
+ end
+
+ def simplify
+ begin
+ return Expr.build [:number, evaluate]
+ rescue UndefinedVariableError
+ return - Expr.build(operand).simplify
+ end
+ end
+
+ def derive(variable)
+ - Expr.build(operand).derive(variable)
+ end
+end
+
+class Sine < Unary
+ def evaluate(environment = {})
+ Math.sin Expr.build(operand).evaluate(environment)
+ end
+
+ def simplify
+ begin
+ return Expr.build [:number, evaluate]
+ rescue UndefinedVariableError
+ return Expr.build [:sin, Expr.build(operand).simplify.s_expr]
+ end
+ end
+
+ def derive(variable)
+ Expr.build(operand).derive(variable) * Cosine.build(operand)
+ end
+end
+
+class Cosine < Unary
+ def evaluate(environment = {})
+ Math.cos Expr.build(operand).evaluate(environment)
+ end
+
+ def simplify
+ begin
+ return Expr.build [:number, evaluate]
+ rescue UndefinedVariableError
+ return Expr.build [:cos, Expr.build(operand).simplify.s_expr]
+ end
+ end
+
+ def derive(variable)
+ Expr.build(operand).derive(variable) * (- Sine.build(operand))
+ end
+end