Станислав обнови решението на 13.11.2012 14:43 (преди около 12 години)
+class Expr
+ def self.build(expr)
+ return expr if not expr.kind_of? Array
+ {
+ :number => Number,
+ :variable => Variable,
+ :+ => AdditionOperator,
+ :* => MultiplicationOperator,
+ :- => NegationOperator,
+ :sin => Sine,
+ :cos => Cosine,
+ }[expr[0]].new *expr[1..-1].map { |arg| Expr.build arg }
+ end
+
+ def ==(other)
+ self.class == other.class
+ end
+
+ def derive(variable)
+ derivative(variable).simplify
+ end
+end
+
+class Operand < Expr
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def ==(other)
+ super other and @value == other.value
+ end
+end
+
+class Variable < Operand
+ def evaluate(environment)
+ environment[@value]
+ end
+
+ def simplify
+ self.class.new @value
+ end
+
+ def derivative(variable)
+ Number.new @value == variable ? 1 : 0
+ end
+end
+
+class Number < Operand
+ def evaluate(environment)
+ @value
+ end
+
+ def simplify
+ self.class.new @value
+ end
+
+ def derivative(variable)
+ self.class.new 0
+ end
+end
+
+class Operator < Expr
+end
+
+class UnaryOperator < Operator
+ attr_reader :arg
+
+ def initialize(arg)
+ @arg = arg.simplify
+ end
+
+ def ==(other)
+ super other and @arg == other.arg
+ end
+end
+
+class BinaryOperator < Operator
+ attr_reader :first_arg, :second_arg
+
+ def initialize(first_arg, second_arg)
+ @first_arg, @second_arg = first_arg.simplify, second_arg.simplify
+ end
+
+ def ==(other)
+ super other and @first_arg == other.first_arg and @second_arg == other.second_arg
+ end
+end
+
+class Sine < UnaryOperator
+ def evaluate(environment)
+ Math.sin @arg.evaluate environment
+ end
+
+ def simplify
+ self.class.new @arg.simplify
+ end
+
+ def derivative(variable)
+ MultiplicationOperator.new Cosine.new(@arg), @arg.derive(variable)
+ end
+end
+
+class Cosine < UnaryOperator
+ def evaluate(environment)
+ Math.cos @arg.evaluate environment
+ end
+
+ def simplify
+ self.class.new @arg.simplify
+ end
+
+ def derivative(variable)
+ MultiplicationOperator.new NegationOperator.new(Sine.new @arg), @arg.derive(variable)
+ end
+end
+
+class NegationOperator < UnaryOperator
+ def evaluate(environment)
+ -@arg.evaluate(environment)
+ end
+
+ def simplify
+ self.class.new @arg.simplify
+ end
+
+ def derivative(variable)
+ self.class.new -@arg.derive(variable)
+ end
+end
+
+class AdditionOperator < BinaryOperator
+ def evaluate(environment)
+ @first_arg.evaluate(environment) + @second_arg.evaluate(environment)
+ end
+
+ def simplify
+ first_arg, second_arg = @first_arg.simplify, @second_arg.simplify
+ if first_arg.kind_of? Number and second_arg.kind_of? Number
+ Number.new first_arg.value + second_arg.value
+ elsif first_arg == Number.new(0)
+ second_arg
+ elsif second_arg == Number.new(0)
+ first_arg
+ else
+ self.class.new first_arg, second_arg
+ end
+ end
+
+ def derivative(variable)
+ self.class.new @first_arg.derive(variable), @second_arg.derive(variable)
+ end
+end
+
+class MultiplicationOperator < BinaryOperator
+ def evaluate(environment)
+ @first_arg.evaluate(environment) * @second_arg.evaluate(environment)
+ end
+
+ def simplify
+ first_arg, second_arg = @first_arg.simplify, @second_arg.simplify
+ if first_arg.kind_of?(Number) and second_arg.kind_of?(Number)
+ Number.new first_arg.value * second_arg.value
+ elsif first_arg == Number.new(0) or second_arg == Number.new(0)
+ Number.new 0
+ elsif first_arg == Number.new(1)
+ second_arg
+ elsif second_arg == Number.new(1)
+ first_arg
+ else
+ self.class.new first_arg, second_arg
+ end
+ end
+
+ def derivative(variable)
+ first_arg = self.class.new @first_arg.derive(variable), @second_arg
+ second_arg = self.class.new @first_arg, @second_arg.derive(variable)
+ AdditionOperator.new first_arg, second_arg
+ end
+end