Решение на Втора задача от Иван Станков

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

Към профила на Иван Станков

Резултати

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

Код

class NumberSet
include Enumerable
def initialize(array = [])
@array = array
end
def each(&block)
@array.each(&block)
end
def <<(number)
@array << number unless @array.include? number
end
def size
@array.size
end
def empty?
@array.empty?
end
def [] (filter)
NumberSet.new(filter.apply_filter(@array))
end
end
class Filter
def initialize(&block)
@block = block
end
def apply_filter(array)
array.select(&@block)
end
def & (filter)
end
def | (filter)
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def check_type (number)
case @type
when :integer
number.is_a? Integer
when :complex
number.is_a? Complex
when :real
number.is_a? Rational or number.is_a? Float
end
end
def apply_filter(array)
filtered_array = []
array.each do |number|
if check_type(number)
filtered_array << number
end
end
filtered_array
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def check_sign (number)
if @sign == :positive
number > 0
elsif @sign == :non_positive
number <= 0
elsif @sign == :negative
number < 0
elsif @sign == :non_negative
number >= 0
end
end
def apply_filter(array)
filtered_array = []
array.each do |number|
if check_sign(number)
filtered_array << number
end
end
filtered_array
end
end

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

................FFFFFF..

Failures:

  1) NumberSet can combine two filters with "and" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for nil:NilClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:92: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 can combine two filters with "or" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for nil:NilClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:99: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)>'

  3) NumberSet can combine multiple filters with "and" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for false:FalseClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:109: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)>'

  4) NumberSet can combine multiple filters with "or" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for true:TrueClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:119: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)>'

  5) NumberSet can combine multiple filters with "and" and "or" rules
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for true:TrueClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:129: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)>'

  6) NumberSet can combine multiple filters with "and", "or" and parenthesis
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `apply_filter' for nil:NilClass
     # /tmp/d20141028-18133-4vzfvg/solution.rb:24:in `[]'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-4vzfvg/spec.rb:139: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.02146 seconds
24 examples, 6 failures

Failed examples:

rspec /tmp/d20141028-18133-4vzfvg/spec.rb:90 # NumberSet can combine two filters with "and" rule
rspec /tmp/d20141028-18133-4vzfvg/spec.rb:97 # NumberSet can combine two filters with "or" rule
rspec /tmp/d20141028-18133-4vzfvg/spec.rb:104 # NumberSet can combine multiple filters with "and" rule
rspec /tmp/d20141028-18133-4vzfvg/spec.rb:114 # NumberSet can combine multiple filters with "or" rule
rspec /tmp/d20141028-18133-4vzfvg/spec.rb:124 # NumberSet can combine multiple filters with "and" and "or" rules
rspec /tmp/d20141028-18133-4vzfvg/spec.rb:134 # NumberSet can combine multiple filters with "and", "or" and parenthesis

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

Иван обнови решението на 26.10.2014 15:53 (преди над 9 години)

+class NumberSet
+ include Enumerable
+ def initialize(array = [])
+ @array = array
+ end
+
+ def each(&block)
+ @array.each(&block)
+ end
+
+ def <<(number)
+ @array << number unless @array.include? number
+ end
+
+ def size
+ @array.size
+ end
+
+ def empty?
+ @array.empty?
+ end
+
+ def [] (filter)
+ NumberSet.new(filter.apply_filter(@array))
+ end
+end
+
+class Filter
+
+ def initialize(&block)
+ @block = block
+ end
+
+ def apply_filter(array)
+ array.select(&@block)
+ end
+
+ def & (filter)
+ end
+
+ def | (filter)
+ end
+end
+
+
+
+class TypeFilter < Filter
+ def initialize(type)
+ @type = type
+ end
+
+ def check_type (number)
+ case @type
+ when :integer
+ number.is_a? Integer
+ when :complex
+ number.is_a? Complex
+ when :real
+ number.is_a? Rational or number.is_a? Float
+ end
+ end
+
+ def apply_filter(array)
+ filtered_array = []
+ array.each do |number|
+ if check_type(number)
+ filtered_array << number
+ end
+ end
+ filtered_array
+ end
+end
+
+
+class SignFilter < Filter
+ def initialize(sign)
+ @sign = sign
+ end
+
+ def check_sign (number)
+ if @sign == :positive
+ number > 0
+ elsif @sign == :non_positive
+ number <= 0
+ elsif @sign == :negative
+ number < 0
+ elsif @sign == :non_negative
+ number >= 0
+ end
+ end
+ def apply_filter(array)
+ filtered_array = []
+ array.each do |number|
+ if check_sign(number)
+ filtered_array << number
+ end
+ end
+ filtered_array
+ end
+end
  • Моля погледни style guide-a, за да видиш къде следва или не следва да оставяш колко празни реда или space-а.
  • Опитай се да измисляш имена, по-близки до домейна на проблема. @array като име описва само имплементационен детайл. Ако попиташ математик какво съдържа едно Множество от числа, най-вероятно няма да ти каже масив, а числа. Филтрите не филтрират по блок, а по някакво условие.
  • Не мисля, че това apply_filter да приема и връща масив е много добра идея. Ако утре решиш да пренапишеш NumberSet, така че да се представя чрез Set, а не Array ще трябва да го преобразуваш после. Би било по-добре да приема единично число и да казва, дали то удовлетворява или не дадения филтър. Също си написал apply_filter доста процедурно. В Ruby се предпочита по-функционален подход, що се отнася до вътрешности. Разгледай Enumerable#select.
  • Ако имаш проблеми с това как да имплементираш Filter#| и Filter#&, а не просто не си имал време, попитай във форумите/прати email.
  • Когато сравняваш много пъти дали някаква променлива е равна на различни стойности използвай case, както си направил във TypeFilter.