Решение на Втора задача от Божидар Горов

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

Към профила на Божидар Горов

Резултати

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

Код

class NumberSet
include Enumerable
attr_accessor :container
def initialize(initial_container = [])
@container = initial_container
end
def <<(number)
unless @container.include? number
@container << number
end
end
def size
@container.size
end
def empty?
@container.empty?
end
def each(&proc)
@container.each { |e| yield(e) }
end
def [](filter)
NumberSet.new(@container.select(&filter.filter_proc))
end
end
class Filter
attr_accessor :filter_proc
def initialize(&proc)
@filter_proc = proc
end
def &(other)
Filter.new do |number|
@filter_proc.call(number) && other.filter_proc.call(number)
end
end
def |(other)
Filter.new do |number|
@filter_proc.call(number) || other.filter_proc.call(number)
end
end
end
class SignFilter < Filter
def initialize(sign)
@filter_proc = case sign
when :positive then Proc.new { |number| number > 0 }
when :non_positev then Proc.new { |number| number <= 0 }
when :negative then Proc.new { |number| number < 0 }
when :non_negative then Proc.new { |number| number >= 0 }
end
end
end
class TypeFilter < Filter
def initialize(type)
@filter_proc = case type
when :real
Proc.new { |number| number.is_a? Float or number.is_a? Rational }
when :complex
Proc.new { |number| number.is_a? Complex }
when :integer
Proc.new { |number| number.is_a? Integer }
end
end
end

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

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

Failures:

  1) NumberSet can filter non-positive numbers
     Failure/Error: expect(filtered_numbers.size).to eq expecting.size
       
       expected: 2
            got: 3
       
       (compared using ==)
     # /tmp/d20141028-18133-5bht9l/spec.rb:180:in `can_filter'
     # /tmp/d20141028-18133-5bht9l/spec.rb:73:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) NumberSet returns enumerable of set's contents if no block is given to each
     Failure/Error: expect(numbers.each.to_a.size).to eq [1, 3, 5].size
     LocalJumpError:
       no block given (yield)
     # /tmp/d20141028-18133-5bht9l/solution.rb:25:in `block in each'
     # /tmp/d20141028-18133-5bht9l/solution.rb:25:in `each'
     # /tmp/d20141028-18133-5bht9l/solution.rb:25:in `each'
     # /tmp/d20141028-18133-5bht9l/spec.rb:164:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02299 seconds
24 examples, 2 failures

Failed examples:

rspec /tmp/d20141028-18133-5bht9l/spec.rb:72 # NumberSet can filter non-positive numbers
rspec /tmp/d20141028-18133-5bht9l/spec.rb:159 # NumberSet returns enumerable of set's contents if no block is given to each

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

Божидар обнови решението на 26.10.2014 12:54 (преди над 9 години)

+class NumberSet
+ include Enumerable
+
+ attr_accessor :container
+
+ def initialize(initial_container = [])
+ @container = initial_container
+ end
+
+ def <<(number)
+ unless @container.include? number
+ @container << number
+ end
+ end
+
+ def size
+ @container.size
+ end
+
+ def empty?
+ @container.empty?
+ end
+
+ def each(&proc)
+ @container.each { |e| yield(e) }
+ end
+
+ def [](filter)
+ NumberSet.new(@container.select(&filter.filter_proc))
+ end
+
+end
+
+class Filter
+
+ attr_accessor :filter_proc
+
+ def initialize(&proc)
+ @filter_proc = proc
+ end
+
+ def &(other)
+ Filter.new do |number|
+ @filter_proc.call(number) && other.filter_proc.call(number)
+ end
+ end
+
+ def |(other)
+ Filter.new do |number|
+ @filter_proc.call(number) || other.filter_proc.call(number)
+ end
+ end
+
+end
+
+class SignFilter < Filter
+
+ def initialize(sign)
+ @filter_proc = case sign
+ when :positive then Proc.new { |number| number > 0 }
+ when :non_positev then Proc.new { |number| number <= 0 }
+ when :negative then Proc.new { |number| number < 0 }
+ when :non_negative then Proc.new { |number| number >= 0 }
+ end
+ end
+
+end
+
+class TypeFilter < Filter
+
+ def initialize(type)
+ @filter_proc = case type
+ when :real
+ Proc.new { |number| number.is_a? Float or number.is_a? Rational }
+ when :complex
+ Proc.new { |number| number.is_a? Complex }
+ when :integer
+ Proc.new { |number| number.is_a? Integer }
+ end
+ end
+
+end

Здрасти,

Ето няколко неща за размисъл:

  • Не оставяй празен ред преди първия и след последния метод в клас.
  • attr_accessor-ите не са ти необходими.
  • NumberSet#each трябва да работи подобно на Array#each, когато не му подадеш блок.
  • Вместо да даваш стойност на @filter_proc в SignFilter, TypeFilter можеш да подадеш блок на конструктора на Filter използвайки super() { |number| ... }.
  • Скрий @filter_proc.call(number) зад метод. Не е добре да показваш ламбдата на въшния свят. По-добре да имаш стабилен интерфейс.