Решение на Втора задача от Любомир Петков

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

Към профила на Любомир Петков

Резултати

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

Код

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each
@numbers.each {|number| yield number}
end
def <<(number)
unless @numbers.include? number
@numbers << number
end
end
def size
@numbers.size
end
def empty?
size == 0
end
def [](filter)
numbers = NumberSet.new
@numbers.each do |number|
if filter.check.call number
numbers << number
end
end
numbers
end
end
class Filter
attr_accessor :check
def initialize(&check)
@check = check
end
end
class TypeFilter < Filter
def initialize(type)
case type
when :integer then @check = integer
when :real then @check = real
when :complex then @check = complex
end
end
def integer
lambda {|number| number.class == Fixnum}
end
def real
lambda {|number| number.class == Float || number.class == Rational}
end
def complex
lambda {|number| number.class == Complex}
end
end
class SignFilter < Filter
def initialize(sign)
case sign
when :positive then @check = positive
when :non_positive then @check = non_positive
when :negative then @check = negative
when :non_negative then @check = non_negative
end
end
def positive
lambda {|number| number > 0}
end
def non_positive
lambda {|number| number <= 0}
end
def negative
lambda {|number| number < 0}
end
def non_negative
lambda {|number| number >= 0}
end
end

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

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

Failures:

  1) 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:0xba044858>
     # /tmp/d20141028-18133-1752mg7/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)>'

  2) 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:0xba03fe0c>
     # /tmp/d20141028-18133-1752mg7/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)>'

  3) NumberSet can combine multiple filters with "and" rule
     Failure/Error: filter        = non_negative & non_zero & mod_3_is_zero
     NoMethodError:
       undefined method `&' for #<SignFilter:0xba03f358>
     # /tmp/d20141028-18133-1752mg7/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)>'

  4) NumberSet can combine multiple filters with "or" rule
     Failure/Error: filter        = even | negative | more_than_100
     NoMethodError:
       undefined method `|' for #<Filter:0xba03e804 @check=#<Proc:0xba03e840>>
     # /tmp/d20141028-18133-1752mg7/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)>'

  5) NumberSet can combine multiple filters with "and" and "or" rules
     Failure/Error: filter        = even & negative | mod_3_is_zero
     NoMethodError:
       undefined method `&' for #<Filter:0xba03dcc4 @check=#<Proc:0xba03e840>>
     # /tmp/d20141028-18133-1752mg7/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)>'

  6) NumberSet can combine multiple filters with "and", "or" and parenthesis
     Failure/Error: filter        = even & (negative | mod_3_is_zero)
     NoMethodError:
       undefined method `|' for #<SignFilter:0xba03d170>
     # /tmp/d20141028-18133-1752mg7/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)>'

  7) 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-1752mg7/solution.rb:9:in `block in each'
     # /tmp/d20141028-18133-1752mg7/solution.rb:9:in `each'
     # /tmp/d20141028-18133-1752mg7/solution.rb:9:in `each'
     # /tmp/d20141028-18133-1752mg7/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.02085 seconds
24 examples, 7 failures

Failed examples:

rspec /tmp/d20141028-18133-1752mg7/spec.rb:90 # NumberSet can combine two filters with "and" rule
rspec /tmp/d20141028-18133-1752mg7/spec.rb:97 # NumberSet can combine two filters with "or" rule
rspec /tmp/d20141028-18133-1752mg7/spec.rb:104 # NumberSet can combine multiple filters with "and" rule
rspec /tmp/d20141028-18133-1752mg7/spec.rb:114 # NumberSet can combine multiple filters with "or" rule
rspec /tmp/d20141028-18133-1752mg7/spec.rb:124 # NumberSet can combine multiple filters with "and" and "or" rules
rspec /tmp/d20141028-18133-1752mg7/spec.rb:134 # NumberSet can combine multiple filters with "and", "or" and parenthesis
rspec /tmp/d20141028-18133-1752mg7/spec.rb:159 # NumberSet returns enumerable of set's contents if no block is given to each

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

Любомир обнови решението на 26.10.2014 23:13 (преди около 10 години)

+class NumberSet
+ include Enumerable
+
+ attr_accessor :numbers
+
+ def initialize
+ @numbers = []
+ end
+
+ def each
+ @numbers.each {|number| yield number}
+ end
+
+ def <<(number)
+ if ! @numbers.include? number
+ @numbers << number
+ end
+ end
+
+ def size
+ @numbers.count
+ end
+
+ def empty?
+ size == 0
+ end
+end

Имплементираш ли Enumerable обект трябва да му дефинираш each метода. По този начин дефинираш как се обхождат елементите на този обект. Кодът ти работи и без него засега понеже не си пробвал да извикаш някои от методите, които идват от Enumerable.

Ето няколко други коментара:

  • attr_accessor не ти трябва
  • if !... е същото като unless .... Предпочитаме второто.
  • Предпочитай Array#size метода пред Array#count. Провери какво точно правят и каква е разликата.

Продължавай с останалата част от задачата. :)

Любомир обнови решението на 27.10.2014 13:55 (преди около 10 години)

class NumberSet
include Enumerable
- attr_accessor :numbers
-
def initialize
@numbers = []
end
- def each
+ def each
@numbers.each {|number| yield number}
end
def <<(number)
- if ! @numbers.include? number
+ unless @numbers.include? number
@numbers << number
end
end
def size
- @numbers.count
+ @numbers.size
end
def empty?
size == 0
+ end
+
+ def [](filter)
+ numbers = NumberSet.new
+
+ @numbers.each do |number|
+ if filter.check.call number
+ numbers << number
+ end
+ end
+
+ numbers
+ end
+end
+
+class SuperFilter
+
+ attr_accessor :check
+
+# & |
+end
+
+class Filter < SuperFilter
+
+ def initialize(&check)
+ @check = check
+ end
+end
+
+class TypeFilter < SuperFilter
+
+ def initialize(type)
+ case type
+ when :integer then @check = integer
+ when :real then @check = real
+ when :complex then @check = complex
+ end
+ end
+
+ def integer
+ lambda {|number| number.class == Fixnum}
+ end
+
+ def real
+ lambda {|number| number.class == Float || number.class == Rational}
+ end
+
+ def complex
+ lambda {|number| number.class == Complex}
+ end
+end
+
+class SignFilter < SuperFilter
+
+ def initialize(sign)
+ case sign
+ when :positive then @check = positive
+ when :non_positive then @check = non_positive
+ when :negative then @check = negative
+ when :non_negative then @check = non_negative
+ end
+ end
+
+ def positive
+ lambda {|number| number > 0}
+ end
+
+ def non_positive
+ lambda {|number| number <= 0}
+ end
+
+ def negative
+ lambda {|number| number < 0}
+ end
+
+ def non_negative
+ lambda {|number| number >= 0}
end
end

Любомир обнови решението на 27.10.2014 14:13 (преди около 10 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each
@numbers.each {|number| yield number}
end
def <<(number)
unless @numbers.include? number
@numbers << number
end
end
def size
@numbers.size
end
def empty?
size == 0
end
def [](filter)
numbers = NumberSet.new
@numbers.each do |number|
if filter.check.call number
numbers << number
end
end
numbers
end
end
-class SuperFilter
+class Filter
attr_accessor :check
-# & |
-end
-
-class Filter < SuperFilter
-
def initialize(&check)
@check = check
end
end
-class TypeFilter < SuperFilter
+class TypeFilter < Filter
def initialize(type)
case type
when :integer then @check = integer
when :real then @check = real
when :complex then @check = complex
end
end
def integer
lambda {|number| number.class == Fixnum}
end
def real
lambda {|number| number.class == Float || number.class == Rational}
end
def complex
lambda {|number| number.class == Complex}
end
end
-class SignFilter < SuperFilter
+class SignFilter < Filter
def initialize(sign)
case sign
when :positive then @check = positive
when :non_positive then @check = non_positive
when :negative then @check = negative
when :non_negative then @check = non_negative
end
end
def positive
lambda {|number| number > 0}
end
def non_positive
lambda {|number| number <= 0}
end
def negative
lambda {|number| number < 0}
end
def non_negative
lambda {|number| number >= 0}
end
end

Не мога да повярвам колко близо бях! Аргх! В крайна сметка целях нещо като решението на Камен Станев. След добавяне на

def &(other) Filter.new{|x| check.call x and other.check.call x} end

и

def |(other) Filter.new{|x| check.call x or other.check.call x} end

програмата минава тестовете. Дейм! :D