Решение на Втора задача от Бисер Кръстев

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

Към профила на Бисер Кръстев

Резултати

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

Код

class Filter
def initialize(&bl)
@block = bl
end
def check(value)
@block.call value
end
def &(other)
Filter.new { |x| self.check x and other.check x}
end
def |(other)
Filter.new { |x| self.check x or other.check x }
end
end
class SignFilter < Filter
def initialize(sign)
case sign
when :positive then @block = ->(x) { x > 0 }
when :negative then @block = ->(x) { x < 0 }
when :non_positive then @block = ->(x) { x <= 0 }
when :non_negative then @block = ->(x) { x >= 0 }
end
end
end
class TypeFilter < Filter
def initialize(sign)
case sign
when :integer then @block = ->(x) { x.is_a? Integer }
when :real then @block = ->(x) { x.is_a? Float or x.is_a? Rational }
when :complex then @block = ->(x) { x.is_a? Complex }
end
end
end
class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given? then
block.call number
else
yield number
end
end
end
def size
@numbers.size
end
def empty?
@numbers.size == 0
end
def check_type(number)
number.is_a? Fixnum or
number.is_a? Float or
number.is_a? Rational or
number.is_a? Complex
end
def <<(number)
return nil if @numbers.include? number
return nil if not check_type number
@numbers.push number
end
def [](filter)
@numbers.select { |x| filter.check x }
end
end

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

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

Failures:

  1) 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-igfszb/solution.rb:58:in `block in each'
     # /tmp/d20141028-18133-igfszb/solution.rb:54:in `each'
     # /tmp/d20141028-18133-igfszb/solution.rb:54:in `each'
     # /tmp/d20141028-18133-igfszb/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.02241 seconds
24 examples, 1 failure

Failed examples:

rspec /tmp/d20141028-18133-igfszb/spec.rb:159 # NumberSet returns enumerable of set's contents if no block is given to each

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

Бисер обнови решението на 23.10.2014 16:11 (преди около 10 години)

+class Filter
+
+ def initialize(&bl)
+ @block = bl
+ end
+
+ def check(value)
+ @block.call value
+ end
+
+ def &(other)
+ Filter.new { |x| self.check x and other.check x}
+ end
+
+ def |(other)
+ Filter.new { |x| self.check x or other.check x }
+ end
+
+end
+
+class SignFilter < Filter
+
+ def initialize(sign)
+ case sign
+ when :positive then @block = ->(x) { x > 0 }
+ when :negative then @block = ->(x) { x < 0 }
+ when :non_positive then @block = ->(x) { x <= 0 }
+ when :non_negative then @block = ->(x) { x >= 0 }
+ end
+ end
+
+end
+
+class TypeFilter < Filter
+
+ def initialize(sign)
+ case sign
+ when :integer then @block = ->(x) { x.is_a? Integer }
+ when :real then @block = ->(x) { x.is_a? Float or x.is_a? Rational }
+ when :complex then @block = ->(x) { x.is_a? Complex }
+ end
+ end
+
+end
+
+class NumberSet
+ include Enumerable
+
+ def initialize
+ @numbers = []
+ end
+
+ def each &block
+ @numbers.each do |number|
+ if block_given? then
+ block.call number
+ else
+ yield number
+ end
+ end
+ end
+
+ def size
+ @numbers.size
+ end
+
+ def check_type(number)
+ number.is_a? Fixnum or
+ number.is_a? Float or
+ number.is_a? Rational or
+ number.is_a? Complex
+ end
+
+ def <<(number)
+ return nil if @numbers.include? number
+ return nil if not checkType number
+
+ @numbers.push number
+ end
+
+ def [](filter)
+ select { |x| filter.check x }
+ end
+end

Бисер обнови решението на 24.10.2014 17:12 (преди около 10 години)

class Filter
def initialize(&bl)
@block = bl
end
def check(value)
@block.call value
end
def &(other)
Filter.new { |x| self.check x and other.check x}
end
def |(other)
Filter.new { |x| self.check x or other.check x }
end
end
class SignFilter < Filter
def initialize(sign)
case sign
when :positive then @block = ->(x) { x > 0 }
when :negative then @block = ->(x) { x < 0 }
when :non_positive then @block = ->(x) { x <= 0 }
when :non_negative then @block = ->(x) { x >= 0 }
end
end
end
class TypeFilter < Filter
def initialize(sign)
case sign
when :integer then @block = ->(x) { x.is_a? Integer }
when :real then @block = ->(x) { x.is_a? Float or x.is_a? Rational }
when :complex then @block = ->(x) { x.is_a? Complex }
end
end
end
class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given? then
block.call number
else
yield number
end
end
end
def size
@numbers.size
end
+ def empty?
+ @numbers.size == 0
+ end
+
def check_type(number)
number.is_a? Fixnum or
number.is_a? Float or
number.is_a? Rational or
number.is_a? Complex
end
def <<(number)
return nil if @numbers.include? number
- return nil if not checkType number
+ return nil if not check_type number
@numbers.push number
end
def [](filter)
- select { |x| filter.check x }
+ @numbers.select { |x| filter.check x }
end
end

Здрасти,

Решението ти е добро. Имам няколко коментара по кода:

  • Не оставяй празен ред преди първия и след последния метод в клас.
  • Защо bl? block не е чак толкова по-трудно за изписване. :)
  • Можеш ли да измислиш по-добро име за Filter#check? До колкото разбирам връща булева стойност, а ние имаме конвенция за подобни методи.
  • В SignFilter и TypeFilter можеш да замениш даването на стойност на "магическото" поле @block с подаване на блок на конструктора на Filter. Това можеш да постигнеш със super() { |number| ... }
  • Помисли си каква е разликата между block.call number и yield number в NumberSet#each. Провери как се държи Array#each, когато не му е подаден блок. Очакваме NumberSet#each да се държи по същия начин. Липсват ти скобите около параметъра на метода.
  • NumberSet#size е неправилно идентиран.
  • check_type е ненужен според мен. Няма да тестваме с некоректен вход.
  • Вместо Array#push можеш да ползваш Array#<<.
  • Очакваме NumberSet обект като резултат от NumberSet#[]. В момента връщаш Array обект.