Елена обнови решението на 14.11.2012 15:31 (преди около 12 години)
+module ArithmeticExpression
+ class Expr
+ attr_accessor :members
+
+ def initialize(members)
+ @members = members
+ end
+
+ def self.build(members)
+ if members.length == 3
+ Binary.build(members)
+ else
+ Unary.build(members)
+ end
+ end
+
+ def ==(other)
+ @members.eql?(other.members)
+ end
+
+ def evaluate(environment)
+ end
+
+ def simplify
+ end
+
+ def derive(variable)
+ end
+ end
+
+ class Unary < Expr
+ attr_accessor :expr
+
+ def initialize(members)
+ super(members)
+ @expr = members[1]
+ end
+
+ def self.build(members)
+ case members.first
+ when :number then Number.new(members)
+ when :variable then Variable.new(members)
+ when :- then Negation.new(members)
+ when :sin then Sine.new(members)
+ when :cos then Cosine.new(members)
+ end
+ end
+ end
+
+ class Binary < Expr
+ attr_accessor :left_expr, :right_expr
+
+ def initialize(members)
+ super(members)
+ @left_expr = members[1]
+ @right_expr = members[2]
+ end
+
+ def self.build(members)
+ case members.first
+ when :+ then Addition.new(members)
+ when :* then Multiplication.new(members)
+ end
+ end
+ end
+
+ class Number < Unary
+
+ def evaluate(environment)
+ @expr
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ Expr.build([:number, 0])
+ end
+ end
+
+ class Addition < Binary
+
+ def evaluate(environment)
+ Expr.build(@left_expr).evaluate(environment) + Expr.build(@right_expr).evaluate(environment)
+ end
+
+ def simplify
+ left_simplify = Expr.build(@left_expr).simplify
+ right_simplify = Expr.build(@right_expr).simplify
+ addition = Expr.build([:+, left_simplify.members, right_simplify.members]).remove_zeros
+ if left_simplify.kind_of?(Number) and right_simplify.kind_of?(Number)
+ return Expr.build([:number, addition.evaluate({})])
+ end
+ return addition
+ end
+
+ def remove_zeros
+ if Expr.build(@left_expr).members == [:number, 0]
+ return Expr.build(@right_expr)
+ end
+ if Expr.build(@right_expr).members == [:number, 0]
+ return Expr.build(@left_expr)
+ end
+ return self
+ end
+
+ def derive(variable)
+ left_derive = Expr.build(@left_expr).derive(variable)
+ right_derive = Expr.build(@right_expr).derive(variable)
+ Expr.build([:+, left_derive.members, right_derive.members]).simplify
+ end
+ end
+
+ class Multiplication < Binary
+
+ def evaluate(environment)
+ Expr.build(@left_expr).evaluate(environment) * Expr.build(@right_expr).evaluate(environment)
+ end
+
+ def simplify
+ left_simplify = Expr.build(@left_expr).simplify
+ right_simplify = Expr.build(@right_expr).simplify
+ multiplication = Expr.build([:*, left_simplify.members, right_simplify.members]).remove_0_1
+ if left_simplify.kind_of?(Number) and right_simplify.kind_of?(Number)
+ return Expr.build([:number, multiplication.evaluate({})])
+ end
+ return multiplication
+ end
+
+ def remove_0_1
+ if @left_expr == [:number, 0] or @right_expr == [:number, 0]
+ return Expr.build([:number, 0])
+ end
+ if @left_expr == [:number, 1]
+ return Expr.build(@right_expr)
+ end
+ if @right_expr == [:number, 1]
+ return Expr.build(@left_expr)
+ end
+ return self
+ end
+
+ def derive(variable)
+ left = Expr.build(@left_expr).derive(variable)
+ right = Expr.build(@right_expr).derive(variable)
+ Expr.build([:+, [:*, left.members, @right_expr], [:*, @left_expr, right.members]]).simplify
+ end
+ end
+
+ class Variable < Unary
+ def evaluate(environment)
+ environment.each do |key, value|
+ if key==@expr
+ return value
+ end
+ end
+ raise "Can't define the variable #{@expr}!"
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ if @expr == variable
+ return Expr.build([:number, 1])
+ else
+ return Expr.build([:number, 0])
+ end
+ end
+ end
+
+ class Negation < Unary
+ def evaluate(environment)
+ -(Expr.build(@expr).evaluate(environment))
+ end
+
+ def simplify
+ expr_simplify = Expr.build(@expr).simplify
+ negation = Expr.build([:-, expr_simplify.members])
+ return negation
+ end
+
+ def derive(variable)
+ expr_derive = Expr.build(@expr).derive(variable)
+ Expr.build([:-, expr_derive.members]).simplify
+ end
+ end
+
+ class Sine < Unary
+ def evaluate(environment)
+ Math.sin(Expr.build(@expr).evaluate(environment))
+ end
+
+ def simplify
+ expr_simplify = Expr.build(@expr).simplify
+ sine = Expr.build([:sin, expr_simplify.members])
+ if expr_simplify.kind_of?(Number)
+ return Expr.build([:number, sine.evaluate({})])
+ end
+ return sine
+ end
+
+ def derive(variable)
+ expr_derive = Expr.build(@expr).derive(variable)
+ Expr.build([:*, expr_derive.members, [:cos, @expr]]).simplify
+ end
+ end
+
+ class Cosine < Unary
+ def evaluate(environment)
+ Math.cos(Expr.build(@expr).evaluate(environment))
+ end
+
+ def simplify
+ expr_simplify = Expr.build(@expr).simplify
+ cosine = Expr.build([:cos, expr_simplify.members])
+ if expr_simplify.kind_of?(Number)
+ return Expr.build([:number, cosine.evaluate({})])
+ end
+ return cosine
+ end
+
+ def derive(variable)
+ expr_derive = Expr.build(@expr).derive(variable)
+ Expr.build([:*, expr_derive.members, [:-, [:sin, @expr]]]).simplify
+ end
+ end
+end