Решение на Трета задача от Георги Гърдев

Обратно към всички решения

Към профила на Георги Гърдев

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 12 успешни тест(а)
  • 1 неуспешни тест(а)

Код

class Expr
attr_reader :object
def initialize(object)
@object = object
end
def self.build(expression)
case expression.count
when 2 then Unary.build expression
when 3 then Binary.build expression
end
end
def evaluate(environment = {})
@object.evaluate environment
end
def derive(variable)
@object.derive variable
end
def simplify
evaluate if exact?
@object.simplify
end
def exact?
@object.exact?
end
def +(other)
Addition.new self.simplify, other.simplify
end
def *(other)
Multiplication.new self.simplify, other.simplify
end
def -@
Negation.new self.simplify
end
end
class Unary < Expr
attr_reader :object
def self.build(expression)
case expression[0]
when :number then Number.build expression[1]
when :variable then Variable.build expression[1]
when :- then Negation.build expression[1]
when :sin then Sine.build expression[1]
when :cos then Cosine.build expression[1]
end
end
def exact?
@object.exact?
end
def ==(other)
return false if self.class != other.class
@object == other.object
end
end
class Binary < Expr
attr_reader :object1, :object2
def initialize(object1, object2)
@object1, @object2 = object1, object2
end
def self.build(expression)
case expression[0]
when :+ then Addition.build(expression[1], expression[2])
when :* then Multiplication.build(expression[1], expression[2])
end
end
def exact?
@object1.exact? and @object2.exact?
end
def ==(other)
return false if self.class != other.class
object1 == other.object1 and object2 == other.object2
end
end
class Number < Unary
def self.build(value)
new value
end
def evaluate(environment = {})
@object
end
def derive(variable)
new 0
end
def simplify
self
end
def exact?
true
end
end
class Variable < Unary
def self.build(expression)
new expression
end
def evaluate(environment = {})
if environment.has_key? @object
environment[@object]
else
raise "There's no variable #{@variable} in the environment"
end
end
def derive(variable)
Number.new variable == @object ? 1 : 0
end
def simplify
self
end
def exact?
false
end
end
class Negation < Unary
def self.build(expression)
-Expr.build(expression)
end
def evaluate(environment = {})
-@object.evaluate(environment)
end
def derive(variable)
-@object.derive(variable)
end
def simplify
return Number.new(evaluate) if exact?
-@object.simplify
end
end
class Sine < Unary
def self.build(expression)
new Expr.build(expression)
end
def evaluate(environment = {})
Math.sin @object.evaluate(environment)
end
def derive(variable)
@object.derive(variable) * Cosine.new(@object)
end
def simplify
return Number.new(evaluate) if exact?
Sine.new @object.simplify
end
end
class Cosine < Unary
def self.build(expression)
new Expr.build(expression)
end
def evaluate(environment = {})
Math.cos @object.evaluate(environment)
end
def derive(variable)
@object.derive(variable) * -Sine.new(@object)
end
def simplify
return Number.new(evaluate) if exact?
Cosine.new @object.simplify
end
end
class Addition < Binary
def self.build(expression1, expression2)
Expr.build(expression1) + Expr.build(expression2)
end
def evaluate(environment = {})
@object1.evaluate(environment) + @object2.evaluate(environment)
end
def derive(variable)
result = @object1.derive(variable) + @object2.derive(variable)
result.simplify
end
def simplify
zero_as_object = Expr.build([:number, 0])
return Number.new(evaluate) if exact?
return @object1.simplify if @object2 == zero_as_object
return @object2.simplify if @object1 == zero_as_object
(@object1.simplify + @object2.simplify)
end
end
class Multiplication < Binary
def self.build(expression1, expression2)
Expr.build(expression1) * Expr.build(expression2)
end
def evaluate(environment = {})
@object1.evaluate(environment) * @object2.evaluate(environment)
end
def derive(variable)
result = (@object1.derive(variable) * @object2) + (@object1 * @object2.derive(variable))
result.simplify
end
def simplify
one_as_object = Expr.build([:number, 1])
zero_as_object = Expr.build([:number, 0])
return Number.new(evaluate) if exact?
return @object1.simplify if @object2 == one_as_object
return @object2.simplify if @object1 == one_as_object
return Number.new 0 if @object1 == zero_as_object || @object2 == zero_as_object
(@object1.simplify * @object2.simplify).simplify
end
end

Лог от изпълнението

...F.........

Failures:

  1) Expressions assignment can derive expressions
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /tmp/d20130203-23049-1ozjbuu/solution.rb:5

Finished in 0.11072 seconds
13 examples, 1 failure

Failed examples:

rspec /tmp/d20130203-23049-1ozjbuu/spec.rb:160 # Expressions assignment can derive expressions

История (1 версия и 0 коментара)

Георги обнови решението на 14.11.2012 01:15 (преди над 11 години)

+class Expr
+ attr_reader :object
+
+ def initialize(object)
+ @object = object
+ end
+
+ def self.build(expression)
+ case expression.count
+ when 2 then Unary.build expression
+ when 3 then Binary.build expression
+ end
+ end
+
+ def evaluate(environment = {})
+ @object.evaluate environment
+ end
+
+ def derive(variable)
+ @object.derive variable
+ end
+
+ def simplify
+ evaluate if exact?
+ @object.simplify
+ end
+
+ def exact?
+ @object.exact?
+ end
+
+ def +(other)
+ Addition.new self.simplify, other.simplify
+ end
+
+ def *(other)
+ Multiplication.new self.simplify, other.simplify
+ end
+
+ def -@
+ Negation.new self.simplify
+ end
+end
+
+class Unary < Expr
+ attr_reader :object
+
+ def self.build(expression)
+ case expression[0]
+ when :number then Number.build expression[1]
+ when :variable then Variable.build expression[1]
+ when :- then Negation.build expression[1]
+ when :sin then Sine.build expression[1]
+ when :cos then Cosine.build expression[1]
+ end
+ end
+
+ def exact?
+ @object.exact?
+ end
+
+ def ==(other)
+ return false if self.class != other.class
+ @object == other.object
+ end
+end
+
+class Binary < Expr
+ attr_reader :object1, :object2
+
+ def initialize(object1, object2)
+ @object1, @object2 = object1, object2
+ end
+
+ def self.build(expression)
+ case expression[0]
+ when :+ then Addition.build(expression[1], expression[2])
+ when :* then Multiplication.build(expression[1], expression[2])
+ end
+ end
+
+ def exact?
+ @object1.exact? and @object2.exact?
+ end
+
+ def ==(other)
+ return false if self.class != other.class
+ object1 == other.object1 and object2 == other.object2
+ end
+end
+
+class Number < Unary
+ def self.build(value)
+ new value
+ end
+
+ def evaluate(environment = {})
+ @object
+ end
+
+ def derive(variable)
+ new 0
+ end
+
+ def simplify
+ self
+ end
+
+ def exact?
+ true
+ end
+end
+
+class Variable < Unary
+ def self.build(expression)
+ new expression
+ end
+
+ def evaluate(environment = {})
+ if environment.has_key? @object
+ environment[@object]
+ else
+ raise "There's no variable #{@variable} in the environment"
+ end
+ end
+
+ def derive(variable)
+ Number.new variable == @object ? 1 : 0
+ end
+
+ def simplify
+ self
+ end
+
+ def exact?
+ false
+ end
+end
+
+class Negation < Unary
+ def self.build(expression)
+ -Expr.build(expression)
+ end
+
+ def evaluate(environment = {})
+ -@object.evaluate(environment)
+ end
+
+ def derive(variable)
+ -@object.derive(variable)
+ end
+
+ def simplify
+ return Number.new(evaluate) if exact?
+ -@object.simplify
+ end
+end
+
+class Sine < Unary
+ def self.build(expression)
+ new Expr.build(expression)
+ end
+
+ def evaluate(environment = {})
+ Math.sin @object.evaluate(environment)
+ end
+
+ def derive(variable)
+ @object.derive(variable) * Cosine.new(@object)
+ end
+
+ def simplify
+ return Number.new(evaluate) if exact?
+ Sine.new @object.simplify
+ end
+end
+
+class Cosine < Unary
+ def self.build(expression)
+ new Expr.build(expression)
+ end
+
+ def evaluate(environment = {})
+ Math.cos @object.evaluate(environment)
+ end
+
+ def derive(variable)
+ @object.derive(variable) * -Sine.new(@object)
+ end
+
+ def simplify
+ return Number.new(evaluate) if exact?
+ Cosine.new @object.simplify
+ end
+end
+
+class Addition < Binary
+ def self.build(expression1, expression2)
+ Expr.build(expression1) + Expr.build(expression2)
+ end
+
+ def evaluate(environment = {})
+ @object1.evaluate(environment) + @object2.evaluate(environment)
+ end
+
+ def derive(variable)
+ result = @object1.derive(variable) + @object2.derive(variable)
+ result.simplify
+ end
+
+ def simplify
+ zero_as_object = Expr.build([:number, 0])
+
+ return Number.new(evaluate) if exact?
+ return @object1.simplify if @object2 == zero_as_object
+ return @object2.simplify if @object1 == zero_as_object
+
+ (@object1.simplify + @object2.simplify)
+ end
+end
+
+class Multiplication < Binary
+ def self.build(expression1, expression2)
+ Expr.build(expression1) * Expr.build(expression2)
+ end
+
+ def evaluate(environment = {})
+ @object1.evaluate(environment) * @object2.evaluate(environment)
+ end
+
+ def derive(variable)
+ result = (@object1.derive(variable) * @object2) + (@object1 * @object2.derive(variable))
+ result.simplify
+ end
+
+ def simplify
+ one_as_object = Expr.build([:number, 1])
+ zero_as_object = Expr.build([:number, 0])
+
+ return Number.new(evaluate) if exact?
+ return @object1.simplify if @object2 == one_as_object
+ return @object2.simplify if @object1 == one_as_object
+ return Number.new 0 if @object1 == zero_as_object || @object2 == zero_as_object
+
+ (@object1.simplify * @object2.simplify).simplify
+ end
+end