Решение на Трета задача от Илия Ячев

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

Към профила на Илия Ячев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 10 успешни тест(а)
  • 3 неуспешни тест(а)

Код

class Expr
def self.build(array)
type = array[0]
return Negation.new(array) if type == :-
return Addition.new(array) if type == :+
return Multiplication.new(array) if type == :*
class_of_type = {number: Number, variable: Variable, sin: Sine, cos: Cosine}
class_of_type[type].new(array)
end
def +(other)
Addition.new([:+,self,other])
end
def *(other)
Multiplication.new([:*,self,other])
end
def -
Negation.new([:-,self])
end
end
class Unary < Expr
def initialize(array)
@type = array.shift
@a = Expr.build array.shift
end
def exact?
@a.exact?
end
def simplify
return [:number, evaluate] if exact?
Expr.build [@type, @a.simplify]
end
end
class Binary < Expr
def initialize(array)
@type = array.shift
@a = Expr.build array.shift
@b = Expr.build array.shift
end
def exact?
@a.exact? and @b.exact?
end
def simplify
return [:number, evaluate] if exact?
Expr.build [@type, @a.simplify, @b.simplify]
end
end
class Number < Unary
def initialize(array)
@type, @a = array
end
def exact?
true
end
def evaluate(environment = {})
@a
end
def simplify
self
end
def derive(variable)
Expr.build([:number,0])
end
end
class Variable < Unary
def initialize(array)
@type, @a = array
end
def exact?
false
end
def evaluate(environment = {})
return environment[@a] if environment[@a]
raise 'There is an uninitialized variable'
end
def simplify
self
end
def derive(variable)
return Expr.build([:number,1]) if @a == variable
Expr.build([:number,0])
end
end
class Negation < Unary
def evaluate(environment = {})
-@a.evaluate(environment)
end
def derive(variable)
-@a.derive(variable)
end
end
class Addition < Binary
def evaluate(environment = {})
@a.evaluate(environment) + @b.evaluate(environment)
end
def simplify
return [:number, evaluate] if exact?
return @b.simplify if @a.simplify.zero?
return @a.simplify if @b.simplify.zero?
Expr.build [@type, @a.simplify, @b.simplify]
end
def derive(variable)
@a.derive(variable) + @b.derive(variable)
end
end
class Multiplication < Binary
def evaluate(environment = {})
@a.evaluate(environment) * @b.evaluate(environment)
end
def simplify
return [:number, evaluate] if exact?
return @b.simplify if @a.simplify == 1
return @a.simplify if @b.simplify == 1
return 0 if @b.simplify.zero? or @a.simplify.zero?
Expr.build [@type, @a.simplify, @b.simplify]
end
def derive(variable)
@a.derive(variable) * @b + @a * @b.derive(variable)
end
end
class Sine < Unary
def evaluate(environment = {})
Math.sin @a.evaluate(environment)
end
def derive(variable)
@a.derive(variable) * Cosine.new(@a)
end
end
class Cosine < Unary
def evaluate(environment = {})
Math.cos @a.evaluate(environment)
end
def derive(variable)
@a.derive(variable) * (-Sine.new(@a))
end
end

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

.FFF.........

Failures:

  1) Expressions assignment supports comparison
     Failure/Error: build('1 + 2 * 3').should eq build('1 + 2 * 3')
       
       expected: #<Addition:0xa1f8d80 @type=:+, @a=#<Number:0xa259040 @type=:number, @a=1>, @b=#<Multiplication:0xa258b90 @type=:*, @a=#<Number:0xa258884 @type=:number, @a=2>, @b=#<Number:0xa2587bc @type=:number, @a=3>>>
            got: #<Addition:0xa028730 @type=:+, @a=#<Number:0xa0284d8 @type=:number, @a=1>, @b=#<Multiplication:0xa028460 @type=:*, @a=#<Number:0xa0283fc @type=:number, @a=2>, @b=#<Number:0xa028104 @type=:number, @a=3>>>
       
       (compared using ==)
       
       Diff:
       
       @@ -1,9 +1,9 @@
       -#<Addition:0xa1f8d80
       - @a=#<Number:0xa259040 @a=1, @type=:number>,
       +#<Addition:0xa028730
       + @a=#<Number:0xa0284d8 @a=1, @type=:number>,
         @b=
       -  #<Multiplication:0xa258b90
       -   @a=#<Number:0xa258884 @a=2, @type=:number>,
       -   @b=#<Number:0xa2587bc @a=3, @type=:number>,
       +  #<Multiplication:0xa028460
       +   @a=#<Number:0xa0283fc @a=2, @type=:number>,
       +   @b=#<Number:0xa028104 @a=3, @type=:number>,
           @type=:*>,
         @type=:+>
     # /tmp/d20130203-23049-u7r9vm/spec.rb:141:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Expressions assignment supports simplification
     Failure/Error: build(string).simplify
     NoMethodError:
       undefined method `zero?' for #<Variable:0xa3f9288 @type=:variable, @a=:x>
     # /tmp/d20130203-23049-u7r9vm/solution.rb:121:in `simplify'
     # /tmp/d20130203-23049-u7r9vm/spec.rb:125:in `simplify'
     # /tmp/d20130203-23049-u7r9vm/spec.rb:146:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Expressions assignment can derive expressions
     Failure/Error: derive('x').should eq build('1')
       
       expected: #<Number:0xa40bc44 @type=:number, @a=1>
            got: #<Number:0xa40f5d8 @type=:number, @a=1>
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -#<Number:0xa40bc44 @a=1, @type=:number>
       +#<Number:0xa40f5d8 @a=1, @type=:number>
     # /tmp/d20130203-23049-u7r9vm/spec.rb:161:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.04447 seconds
13 examples, 3 failures

Failed examples:

rspec /tmp/d20130203-23049-u7r9vm/spec.rb:140 # Expressions assignment supports comparison
rspec /tmp/d20130203-23049-u7r9vm/spec.rb:145 # Expressions assignment supports simplification
rspec /tmp/d20130203-23049-u7r9vm/spec.rb:160 # Expressions assignment can derive expressions

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

Илия обнови решението на 14.11.2012 16:57 (преди над 11 години)

+
+class Expr
+ def self.build(array)
+ type = array[0]
+ return Negation.new(array) if type == :-
+ return Addition.new(array) if type == :+
+ return Multiplication.new(array) if type == :*
+ class_of_type = {number: Number, variable: Variable, sin: Sine, cos: Cosine}
+ class_of_type[type].new(array)
+ end
+
+ def +(other)
+ Addition.new([:+,self,other])
+ end
+
+ def *(other)
+ Multiplication.new([:*,self,other])
+ end
+
+ def -
+ Negation.new([:-,self])
+ end
+end
+
+class Unary < Expr
+ def initialize(array)
+ @type = array.shift
+ @a = Expr.build array.shift
+ end
+
+ def exact?
+ @a.exact?
+ end
+
+ def simplify
+ return [:number, evaluate] if exact?
+ Expr.build [@type, @a.simplify]
+ end
+end
+
+class Binary < Expr
+ def initialize(array)
+ @type = array.shift
+ @a = Expr.build array.shift
+ @b = Expr.build array.shift
+ end
+
+ def exact?
+ @a.exact? and @b.exact?
+ end
+
+ def simplify
+ return [:number, evaluate] if exact?
+ Expr.build [@type, @a.simplify, @b.simplify]
+ end
+end
+
+class Number < Unary
+ def initialize(array)
+ @type, @a = array
+ end
+
+ def exact?
+ true
+ end
+
+ def evaluate(environment = {})
+ @a
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ Expr.build([:number,0])
+ end
+end
+
+class Variable < Unary
+ def initialize(array)
+ @type, @a = array
+ end
+
+ def exact?
+ false
+ end
+
+ def evaluate(environment = {})
+ return environment[@a] if environment[@a]
+ raise 'There is an uninitialized variable'
+ end
+
+ def simplify
+ self
+ end
+
+ def derive(variable)
+ return Expr.build([:number,1]) if @a == variable
+ Expr.build([:number,0])
+ end
+end
+
+class Negation < Unary
+ def evaluate(environment = {})
+ -@a.evaluate(environment)
+ end
+
+ def derive(variable)
+ -@a.derive(variable)
+ end
+end
+
+class Addition < Binary
+ def evaluate(environment = {})
+ @a.evaluate(environment) + @b.evaluate(environment)
+ end
+
+ def simplify
+ return [:number, evaluate] if exact?
+ return @b.simplify if @a.simplify.zero?
+ return @a.simplify if @b.simplify.zero?
+ Expr.build [@type, @a.simplify, @b.simplify]
+ end
+
+ def derive(variable)
+ @a.derive(variable) + @b.derive(variable)
+ end
+end
+
+class Multiplication < Binary
+ def evaluate(environment = {})
+ @a.evaluate(environment) * @b.evaluate(environment)
+ end
+
+ def simplify
+ return [:number, evaluate] if exact?
+ return @b.simplify if @a.simplify == 1
+ return @a.simplify if @b.simplify == 1
+ return 0 if @b.simplify.zero? or @a.simplify.zero?
+ Expr.build [@type, @a.simplify, @b.simplify]
+ end
+
+ def derive(variable)
+ @a.derive(variable) * @b + @a * @b.derive(variable)
+ end
+end
+
+class Sine < Unary
+ def evaluate(environment = {})
+ Math.sin @a.evaluate(environment)
+ end
+
+ def derive(variable)
+ @a.derive(variable) * Cosine.new(@a)
+ end
+end
+
+class Cosine < Unary
+ def evaluate(environment = {})
+ Math.cos @a.evaluate(environment)
+ end
+
+ def derive(variable)
+ @a.derive(variable) * (-Sine.new(@a))
+ end
+end