Петко обнови решението на 14.11.2012 16:13 (преди около 12 години)
+class Expr
+ def self.build(sexp)
+ case sexp.shift
+ when :number then Number.new sexp.shift
+ when :variable then Variable.new sexp.shift
+ when :+ then Expr.build(sexp.shift) + Expr.build(sexp.shift)
+ when :* then Expr.build(sexp.shift) * Expr.build(sexp.shift)
+ when :- then -Expr.build(sexp.shift)
+ when :sin then Sine.new Expr.build(sexp.shift)
+ when :cos then Cosine.new Expr.build(sexp.shift)
+ end
+ end
+
+ def +(other)
+ Addition.new self, other
+ end
+
+ def -@
+ Negation.new self
+ end
+
+ def *(other)
+ Multiplication.new self, other
+ end
+end
+
+class Unary < Expr
+ attr_accessor :value
+
+ def initialize(value)
+ @value = value
+ end
+
+ def ==(other)
+ return false unless self.is_a? other.class
+ @value == other.value
+ end
+
+ def simplify
+ self
+ end
+end
+
+class Binary < Expr
+ attr_accessor :left, :right
+
+ def initialize(left, right)
+ @left, @right = left, right
+ end
+
+ def ==(other)
+ return false unless self.is_a? other.class
+ @left == other.left and @right == other.right
+ end
+end
+
+class Number < Unary
+ def evaluate(environment)
+ @value
+ end
+end
+
+class Addition < Binary
+ def evaluate(environment)
+ @left.evaluate(environment) + @right.evaluate(environment)
+ end
+
+ def simplify
+ sides = [@left.simplify, @right.simplify]
+
+ sides.delete_if { |side| side == Number.new(0) }
+ sides.size > 0 ? sides.inject(:+) : Number.new(0)
+ end
+end
+
+class Multiplication < Binary
+ def evaluate(environment)
+ @left.evaluate(environment) * @right.evaluate(environment)
+ end
+
+ def simplify
+ sides = [@left.simplify, @right.simplify]
+
+ return Number.new(0) if sides.any? { |side| side == Number.new(0) }
+ sides.delete_if { |side| side == Number.new(1) }
+ sides.size > 0 ? sides.inject(:*) : Number.new(1)
+ end
+end
+
+class Variable < Unary
+ def evaluate(environment)
+ environment[value] or raise_exception 'Undefined variable'
+ end
+end
+
+class Negation < Unary
+ def evaluate(environment)
+ -@value.evaluate(environment)
+ end
+
+ def simplify
+ simplified = @value.simplify
+ return Number.new(0) if simplified == Number.new(0)
+ -simplified
+ end
+end
+
+class Sine < Unary
+ def evaluate(environment)
+ Math.sin @value.evaluate(environment)
+ end
+
+ def simplify
+ simplified = @value.simplify
+ return Number.new(0) if simplified == Number.new(0)
+ Sine.new simplified
+ end
+end
+
+class Cosine < Unary
+ def evaluate(environment)
+ Math.cos @value.evaluate(environment)
+ end
+
+ def simplify
+ simplified = @value.simplify
+ return Number.new(1) if simplified == Number.new(0)
+ Cosine.new simplified
+ end
+end