Атанас обнови решението на 14.11.2012 16:38 (преди около 12 години)
+class Expr
+ def self.razb(tree)
+ case tree[0]
+ when :+ then Addition.new razb(tree[1]), razb(tree[2])
+ when :* then Multiplication.new razb(tree[1]), razb(tree[2])
+ when :number then Number.new tree[1]
+ when :variable then Variable.new tree[1]
+ when :sin then Sine.new tree[1]
+ when :cos then Cosine.new tree[1]
+ when :- then Negation.new tree[1]
+ end
+ end
+
+ def self.build(tree)
+ self.razb(tree).simplify
+ end
+
+ def derive(variable)
+ derive(variable).simplify
+ end
+
+ def simplify
+ simplify
+ end
+end
+
+class Number
+ def initialize(number)
+ @number = number
+ end
+
+ def evaluate(value)
+ @number
+ end
+
+ def derive(variable)
+ Number.new 0
+ end
+
+ def zero?
+ self == 0
+ end
+
+ def one?
+ self == 1
+ end
+end
+
+class Variable
+ def initialize(name)
+ @variable = name
+ end
+
+ def same_variable?(other)
+ other == @variable
+ end
+
+ def evaluate(value)
+ if value.member? @variable
+ @variable = value.invert.key @variable
+ else raise 'Undefined variable!'
+ end
+ end
+
+ def derive(variable)
+ if same_variable? variable
+ Number.new 1
+ else
+ Number.new 0
+ end
+ end
+end
+
+class Negation
+ def initialize(value)
+ @value = Expr.razb value
+ end
+
+ def evaluate(value)
+ -(@value.evaluate value)
+ end
+
+ def derive(variable)
+ Negation.new derive(variable)
+ end
+end
+
+class Sine
+ def initialize(value)
+ @value = Expr.razb value
+ end
+
+ def evaluate(value)
+ Math.sin @value.evaluate value
+ end
+
+ def derive(variable)
+ Multiplication.new @value.derive(variable), Cosine.new(@value)
+ end
+
+ def simplify
+ @value.simplify
+ end
+end
+
+class Cosine
+ def initialize(value)
+ if value.kind_of? Expr
+ @value = value
+ else
+ @value = Expr.razb value
+ end
+ end
+
+ def evaluate(value)
+ Math.cos @value.evaluate value
+ end
+
+ def derive(variable)
+ #Multiplication.new @value.derive(variable), Negation.new (Sine.new @value)
+ end
+
+ def simplify
+ @value.simplify
+ end
+end
+
+class Addition
+ attr_accessor :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def evaluate(value)
+ @left.evaluate(value) + @right.evaluate(value)
+ end
+
+ def derive(variable)
+ Addition.new @left.derive(variable), @right.derive(variable)
+ end
+
+ def simplify
+ if @left == Number and @left.zero?
+ @right.class.new @right
+ elsif @right == Number and @right.zero?
+ @left.class.new @left
+ end
+ self
+ end
+end
+
+class Multiplication
+ attr_accessor :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def evaluate(value)
+ @left.evaluate(value) * @right.evaluate(value)
+ end
+
+ def derive(variable)
+ Addition.new (Multiplication.new @left.derive(variable), @right),
+ (Multiplication.new @left, @right.derive(variable))
+ end
+
+ def simplify
+ if @left == Number and @left.zero? or @right == Number and @right.zero?
+ Number 0
+ elsif @left == Number and @left.one?
+ @right.class.new @right
+ elsif @right == Number and @right.one?
+ @left.class.new @left
+ end
+ self
+ end
+end