Явор обнови решението на 14.11.2012 15:53 (преди около 12 години)
+class Expr
+ attr_reader :expression
+
+ def initialize(expression)
+ @expression = expression
+ end
+
+ def self.build(expression)
+ Expr.new(expression)
+ end
+
+ def ==(other)
+ @expression == other.expression
+ end
+
+ def evaluate(values)
+ operation = @expression.first
+ if operation == :+ or operation == :*
+ Binnary.new(@expression.dup).evaluate(values)
+ else
+ Unnary.new(@expression.dup).evaluate(values)
+ end
+ end
+
+ def simpleTree
+ if !exact?
+ [:number, evaluate(1)]
+ else
+ operation = @expression.first
+ if operation == :+ or operation == :*
+ Binnary.new(@expression.dup).simpleTree
+ else
+ Unnary.new(@expression.dup).simpleTree
+ end
+ end
+ end
+
+ def simplify
+ Expr.new(simpleTree)
+ end
+
+ def exact?
+ operation = @expression.first
+ if operation == :+ or operation == :*
+ Binnary.new(@expression.dup).exact?
+ else
+ Unnary.new(@expression.dup).exact?
+ end
+ end
+end
+
+class Binnary < Expr
+ def evaluate(values)
+ operation = @expression.shift
+ case operation
+ when :+ then Plus.new(@expression).evaluate(values)
+ when :* then Mult.new(@expression).evaluate(values)
+ end
+ end
+
+ def simpleTree
+ operation = @expression.shift
+ case operation
+ when :+ then Plus.new(@expression).simpleTree
+ when :* then Mult.new(@expression).simpleTree
+ end
+ end
+
+ def exact?
+ operation = @expression.shift
+ case operation
+ when :+ then Plus.new(@expression).exact?
+ when :* then Mult.new(@expression).exact?
+ end
+ end
+end
+
+class Plus < Expr
+ def initialize(expression)
+ @subExpr1 = expression.first
+ @subExpr2 = expression.last
+ @func1 = @subExpr1.first
+ @func2 = @subExpr1.first
+ end
+
+ def evaluate(values)
+ if @func1 == :number or @func1 == :variable or @func1 == :sin or @func1 == :cos or @func1 == :-
+ Unnary.new(@subExpr1).evaluate(values) + Expr.new(@subExpr2).evaluate(values)
+ elsif @func2 == :number or @func2 == :variable or @func2==:sin or @func2 == :cos or @func2 == :-
+ Expr.new(@subExpr1).evaluate(values) + Unnary.new(@subExpr2).evaluate(values)
+ else
+ Expr.new(@subExpr1).evaluate(values) + Expr.new(@subExpr2).evaluate(values)
+ end
+ end
+
+ def exact?
+ if @func1 == :number or @func1 == :variable or @func1 == :sin or @func1 == :cos or @func1 == :-
+ Unnary.new(@subExpr1).exact? or Expr.new(@subExpr2).exact?
+ elsif @func2 == :number or @func2 == :variable or @func2==:sin or @func2 == :cos or @func2 == :-
+ Expr.new(@subExpr1).exact? or Unnary.new(@subExpr2).exact?
+ else
+ Expr.new(@subExpr1).exact? or Expr.new(@subExpr2).exact?
+ end
+ end
+
+ def simpleTree
+ if(@subExpr1 == [:number, 0])
+ Expr.new(@subExpr2).simpleTree
+ elsif(@subExpr2 == [:number, 0])
+ Expr.new(@subExpr1).simpleTree
+ elsif @func1 == :variable || @func2 == :variable
+ [:*,@subExpr1,@subExpr2]
+ elsif @subExpr1 == [:number, 0] || @subExpr2 == [:number, 0]
+ [:number, 0]
+ else
+ Expr.new([:+,Expr.new(@subExpr1).simpleTree, Expr.new(@subExpr2).simpleTree]).simpleTree
+ end
+ end
+end
+
+class Mult < Expr
+ def initialize(expression)
+ @subExpr1=expression.first
+ @subExpr2=expression.last
+ @func1=@subExpr1.first
+ @func2=@subExpr2.first
+ end
+
+ def evaluate(values)
+ if @func1 == :number or @func1 == :variable or @func1 == :sin or @func1 == :cos or @func1==:-
+ Unnary.new(@subExpr1).evaluate(values) * Expr.new(@subExpr2).evaluate(values)
+ elsif @func2 == :number or @func2 == :variable or @func2 == :sin or @func2 == :cos or @func2==:-
+ Expr.new(@subExpr1).evaluate(values) * Unnary.new(@subExpr2).evaluate(values)
+ else
+ Expr.new(@subExpr1).evaluate(values)*Expr.new(@subExpr2).evaluate(values)
+ end
+ end
+
+ def exact?
+ if @func1 == :number or @func1 == :variable or @func1 == :sin or @func1 == :cos or @func1 == :-
+ Unnary.new(@subExpr1).exact? or Expr.new(@subExpr2).exact?
+ elsif @func2 == :number or @func2 == :variable or @func2==:sin or @func2 == :cos or @func2 == :-
+ Expr.new(@subExpr1).exact? or Unnary.new(@subExpr2).exact?
+ else
+ Expr.new(@subExpr1).exact? or Expr.new(@subExpr2).exact?
+ end
+ end
+
+ def simpleTree
+ if(@subExpr1 == [:number, 1])
+ Expr.new(@subExpr2).simpleTree
+ elsif(@subExpr2 == [:number, 1])
+ Expr.new(@subExpr1).simpleTree
+ elsif @subExpr1 == [:number, 0] || @subExpr2 == [:number, 0]
+ [:number, 0]
+ elsif @func1 == :variable || @func2 == :variable
+ [:*,@subExpr1,@subExpr2]
+ else
+ Expr.new([:*,Expr.new(@subExpr1).simpleTree, Expr.new(@subExpr2).simpleTree]).simpleTree
+ end
+ end
+end
+
+class Unnary < Expr
+ def evaluate(values)
+ case @expression.first
+ when :number then Number.new(@expression).evaluate
+ when :variable then Variable.new(@expression).evaluate(values)
+ when :cos then Cosine.new(@expression).evaluate(values)
+ when :sin then Sine.new(@expression).evaluate(values)
+ when :- then Negation.new(@expression).evaluate(values)
+ end
+ end
+
+ def exact?
+ case @expression.first
+ when :number then false
+ when :variable then true
+ when :cos then Cosine.new(@expression).exact?
+ when :sin then Sine.new(@expression).exact?
+ when :- then Negation.new(@expression).exact?
+ end
+ end
+
+ def simpleTree
+ case @expression.first
+ when :number then @expression
+ when :variable then @expression
+ when :cos then Cosine.new(@expression).simpleTree
+ when :sin then Sine.new(@expression).simpleTree
+ when :- then Negation.new(@expression).simpleTree
+ end
+ end
+end
+
+class Number < Unnary
+ def initialize(expression)
+ @number = expression.last
+ end
+
+ def evaluate
+ @number
+ end
+end
+
+class Variable < Unnary
+ def initialize(expression)
+ @variable = expression.last
+ end
+
+ def evaluate(values)
+ if(values.key? @variable)
+ values[@variable]
+ else
+ raise "The variable '#{@variable}' is not declarated"
+ end
+ end
+end
+
+class Cosine < Unnary
+ def initialize(expression)
+ expression.flatten!(1).shift
+ @subExpression = expression
+ end
+
+ def evaluate(values)
+ Math.cos(Expr.new(@subExpression).evaluate(values))
+ end
+
+ def exact?
+ Expr.new(@subExpression).exact?
+ end
+
+ def simpleTree
+ [:cos, Expr.new(@subExpression).simpleTree]
+ end
+end
+
+class Sine < Unnary
+ def initialize(expression)
+ expression.flatten!(1).shift
+ @subExpression = expression
+ end
+
+ def evaluate(values)
+ Math.sin(Expr.new(@subExpression).evaluate(values))
+ end
+
+ def exact?
+ Expr.new(@subExpression).exact?
+ end
+
+ def simpleTree
+ [:sin, Expr.new(@subExpression).simpleTree]
+ end
+end
+
+class Negation < Unnary
+ def initialize(expression)
+ expression.flatten!(1).shift
+ @subExpression = expression
+ end
+
+ def evaluate(values)
+ 0 - Expr.new(@subExpression).evaluate(values)
+ end
+
+ def exact?
+ Expr.new(@subExpression).exact?
+ end
+
+ def simpleTree
+ [:-, Expr.new(@subExpression).simpleTree]
+ end
+end