Решение на Втора задача от Здравко Георгиев

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

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

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 17 успешни тест(а)
  • 7 неуспешни тест(а)

Код

class NumberSet
include Enumerable
def initialize()
@container = []
@complex_container = []
end
def <<(value)
if ! @complex_container.include? value.to_c
@container.push value
@complex_container.push value.to_c
end
end
def size
@container.count
end
def empty?
@container.empty?
end
def each(&block)
@container.each &block
end
def [](current_filter)
current_filter.filter(@container)
end
end
class Filter
attr_accessor :condition
def initialize(&block)
@condition = block
end
def filter(container)
container.select &condition
end
end
class TypeFilter
attr_accessor :type
attr_accessor :types
def initialize(type)
@type = type
@types = { :integer => Fixnum,
:real => [Rational, Float], :complex => Complex }
end
def filter(container)
container.select { |n| n.instance_of? @types[@type] }
end
end
class SignFilter
attr_accessor :sign
attr_accessor :signs
def initialize(sign)
@sign = sign
@signs = { :positive => ">", :non_positive => "<=",
:negative => "<", :non_negative => ">=" }
end
def filter(container)
container.select {|n| n.send @signs[@sign], 0}
end
end

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

..........F.....FFFFFF..

Failures:

  1) NumberSet can filter by real type
     Failure/Error: filtered_numbers = numbers[using]
     TypeError:
       class or module required
     # /tmp/d20141028-18133-1tyyz1b/solution.rb:56:in `instance_of?'
     # /tmp/d20141028-18133-1tyyz1b/solution.rb:56:in `block in filter'
     # /tmp/d20141028-18133-1tyyz1b/solution.rb:56:in `select'
     # /tmp/d20141028-18133-1tyyz1b/solution.rb:56:in `filter'
     # /tmp/d20141028-18133-1tyyz1b/solution.rb:29:in `[]'
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:55: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 "and" rule
     Failure/Error: filter = SignFilter.new(:non_negative) & Filter.new { |number| number != 0 }
     NoMethodError:
       undefined method `&' for #<SignFilter:0xb994f390>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:91: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 two filters with "or" rule
     Failure/Error: filter = Filter.new { |number| number % 2 == 0 } | Filter.new { |number| number > 5 }
     NoMethodError:
       undefined method `|' for #<Filter:0xb994e7ec>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:98: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 "and" rule
     Failure/Error: filter        = non_negative & non_zero & mod_3_is_zero
     NoMethodError:
       undefined method `&' for #<SignFilter:0xb994dae0>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:108: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 "or" rule
     Failure/Error: filter        = even | negative | more_than_100
     NoMethodError:
       undefined method `|' for #<Filter:0xb994ce4c @condition=#<Proc:0xb994ce88>>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:118: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" and "or" rules
     Failure/Error: filter        = even & negative | mod_3_is_zero
     NoMethodError:
       undefined method `&' for #<Filter:0xb994c2d0 @condition=#<Proc:0xb994ce88>>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:128: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)>'

  7) NumberSet can combine multiple filters with "and", "or" and parenthesis
     Failure/Error: filter        = even & (negative | mod_3_is_zero)
     NoMethodError:
       undefined method `|' for #<SignFilter:0xb98d78cc>
     # /tmp/d20141028-18133-1tyyz1b/spec.rb:138: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.02131 seconds
24 examples, 7 failures

Failed examples:

rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:54 # NumberSet can filter by real type
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:90 # NumberSet can combine two filters with "and" rule
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:97 # NumberSet can combine two filters with "or" rule
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:104 # NumberSet can combine multiple filters with "and" rule
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:114 # NumberSet can combine multiple filters with "or" rule
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:124 # NumberSet can combine multiple filters with "and" and "or" rules
rspec /tmp/d20141028-18133-1tyyz1b/spec.rb:134 # NumberSet can combine multiple filters with "and", "or" and parenthesis

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

Здравко обнови решението на 26.10.2014 14:36 (преди над 9 години)

+class NumberSet
+ include Enumerable
+
+ def initialize()
+ @container = []
+ @complex_container = []
+ end
+
+ def <<(value)
+ if ! @complex_container.include? value.to_c
+ @container.push value
+ @complex_container.push value.to_c
+ end
+ end
+
+ def size
+ @container.count
+ end
+
+ def empty?
+ @container.empty?
+ end
+
+ def each(&block)
+ @container.each &block
+ end
+
+ def [](current_filter)
+ current_filter.filter(@container)
+ end
+end
+
+class Filter
+ attr_accessor :condition
+
+ def initialize(&block)
+ @condition = block
+ end
+
+ def filter(container)
+ container.select &condition
+ end
+end
+
+class TypeFilter
+ attr_accessor :type
+ attr_accessor :types
+
+ def initialize(type)
+ @type = type
+ @types = { :integer => Fixnum,
+ :real => [Rational, Float], :complex => Complex }
+ end
+
+ def filter(container)
+ container.select { |n| n.instance_of? @types[@type] }
+ end
+end
+
+class SignFilter
+ attr_accessor :sign
+ attr_accessor :signs
+
+ def initialize(sign)
+ @sign = sign
+
+ @signs = { :positive => ">", :non_positive => "<=",
+ :negative => "<", :non_negative => ">=" }
+ end
+
+ def filter(container)
+ container.select {|n| n.send @signs[@sign], 0}
+ end
+end
  • Не виждам каква беше целта на @complex_container. Ако погледнеш как работят Array#include? и == за числа, ще разбереш, че правиш нещата доста по-complex, отколкото е нужно да са. (:
  • Правиш черни send магии в SignFilter. Проблемът е достатъчно прост, за да няма нужда от метапрограмиране.
  • Всички attr_accessor-и нямаше причина да съществуват. С тях нарушаваш Law of Dementer, който е един от градивните принципи за добър ООП дизайн. Опитвай се да криеш имплементацията за външния свят и не давай повече достъп, отколкото е нужно.
  • Опитай се да измисляш имена, по-близки до семантиката, която искаш да изкажеш. @container е ясно, че съдържа нещо, въпросът е какво? block е ясно, че е блок, но какво прави? По принцип е добре предикатите да завършват на ?. Тук filter? ще е малко подвеждащо, но се опитай да измислиш име, което да задава въпрос.
  • Какво ще стане с TypeFilter#filter, ако се прави проверка с :real?
  • Не си имплементирал | и & за филтри. Най-лесно би било ако го сложиш във Filter и другите го наследяват. Ако нямаш идея как да започнеш самата имплементация, а не просто не си имал време, не се притеснявай да питаш във форумите/да пратиш email.