Иван обнови решението на 14.11.2012 01:43 (преди около 12 години)
+class Expr
+ attr_reader :spaghetti
+ def initialize(spaghetti)
+ @spaghetti = spaghetti
+ end
+
+ def self.build(spaghetti)
+ Expr.new spaghetti
+ end
+
+ def evaluate(environment = {})
+ Expr.handler(@spaghetti.first).evaluate spaghetti, environment
+ end
+
+ def simplify
+ Expr.handler(@spaghetti.first).simplify @spaghetti
+ end
+
+ def self.base_derive(expr)
+ Expr.handler(expr.first).base_derive
+ end
+
+ def self.handler(wish)
+ case wish
+ when :number then Number
+ when :variable then Variable
+ when :+ then Addition
+ when :- then Negation
+ when :* then Multiplication
+ when :sin then Sine
+ when :cos then Cosine
+ end
+ end
+
+ def ==(other)
+ @spaghetti == other.spaghetti
+ end
+end
+
+module Number
+ ZERO = [:number, 0].freeze
+ ONE = [:number, 1].freeze
+
+ def self.evaluate(expr, environment = {})
+ expr.last
+ end
+
+ def self.simplify(expr)
+ Expr.build expr
+ end
+
+ def self.to_expr(number)
+ Expr.build [:number, number]
+ end
+end
+
+module Variable
+ def self.evaluate(expr, environment = {})
+ raise 'Cannot calculate that!' unless environment.include? expr.last
+ environment[expr.last]
+ end
+
+ def self.simplify(expr)
+ Expr.build expr
+ end
+end
+
+module Addition
+ def self.evaluate(expr, environment = {})
+ Expr.build(expr[1]).evaluate(environment) + Expr.build(expr[2]).evaluate(environment)
+ end
+
+ def self.simplify(expr)
+ if expr.include? Number::ZERO
+ simple = expr[3 - expr.index(Number::ZERO)]
+ Expr.build(simple).simplify
+ else
+ Expr.build(Number.to_expr Expr.build(expr).evaluate)
+ end
+ rescue
+ Expr.build expr
+ end
+end
+
+module Negation
+ def self.evaluate(expr, environment = {})
+ -Expr.build(expr.last).evaluate(environment)
+ end
+
+ def self.simplify(expr)
+ Expr.build expr
+ end
+end
+
+module Multiplication
+ def self.evaluate(expr, environment = {})
+ return 0 if expr.include? Number::ZERO
+ Expr.build(expr[1]).evaluate(environment) * Expr.build(expr[2]).evaluate(environment)
+ end
+
+ def self.simplify(expr)
+ if expr.include? Number::ONE
+ simple = expr[3 - expr.index(Number::ONE)]
+ Number.to_expr Expr.build(simple).evaluate rescue Expr.build simple
+ else
+ Number.to_expr Expr.build(expr).evaluate rescue Expr.build expr
+ end
+ end
+end
+
+module Sine
+ def self.evaluate(expr, environment = {})
+ Math.sin Expr.build(expr[1]).evaluate(environment)
+ end
+
+ def self.simplify(expr)
+ return Number::ZERO if Expr.build(expr).evaluate.zero?
+ Expr.build expr
+ rescue
+ Expr.build expr
+ end
+end
+
+module Cosine
+ def self.evaluate(expr, environment = {})
+ Math.cos Expr.build(expr[1]).evaluate(environment)
+ end
+
+ def self.simplify(expr)
+ return Expr.build Number::ONE if Expr.build(expr).evaluate.zero?
+ Expr.build expr
+ rescue
+ Expr.build expr
+ end
+end