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

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

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

Резултати

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

Код

class NumberSet
include Enumerable
def initialize(numbers = [])
@numbers = numbers
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
NumberSet.new(filter.filter(@numbers))
end
def each(&block)
@numbers.each { |number| block.call number } if block_given?
@numbers.to_enum unless block_given?
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
end
class IntersectionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
class UnionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end

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

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

Failures:

  1) NumberSet can combine two filters with "or" rule
     Failure/Error: expect(filtered_numbers.size).to eq expecting.size
       
       expected: 7
            got: 10
       
       (compared using ==)
     # /tmp/d20141028-18133-23swv/spec.rb:180:in `can_filter'
     # /tmp/d20141028-18133-23swv/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)>'

  2) NumberSet can combine multiple filters with "or" rule
     Failure/Error: expect(filtered_numbers.size).to eq expecting.size
       
       expected: 11
            got: 13
       
       (compared using ==)
     # /tmp/d20141028-18133-23swv/spec.rb:180:in `can_filter'
     # /tmp/d20141028-18133-23swv/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)>'

Finished in 0.02256 seconds
24 examples, 2 failures

Failed examples:

rspec /tmp/d20141028-18133-23swv/spec.rb:97 # NumberSet can combine two filters with "or" rule
rspec /tmp/d20141028-18133-23swv/spec.rb:114 # NumberSet can combine multiple filters with "or" rule

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

Емилиан обнови решението на 21.10.2014 15:10 (преди около 10 години)

+class NumberSet
+ include Enumerable
+
+ def initialize
+ @numbers = []
+ end
+
+ def << number
+ @numbers << number unless @numbers.include? number
+ end
+
+ def size
+ @numbers.size
+ end
+
+ def empty?
+ @numbers.empty?
+ end
+
+ def [](filter)
+ @numbers = filter.filter(@numbers)
+ end
+
+ def each(&block)
+ @numbers.each do |number|
+ if block_given?
+ block.call number
+ else
+ yield number
+ end
+ end
+ end
+end
+
+
+class Filter
+ def initialize(&block)
+ @block = block
+ end
+
+ def filter(numbers)
+ numbers.select(&@block)
+ end
+
+ def & other
+ SectionFilter.new(self, other)
+ end
+
+ def | other
+ UnionFilter.new(self, other)
+ end
+end
+
+
+class SignFilter
+ def initialize(sign)
+ @sign = sign
+ end
+
+ def filter(numbers)
+ filtered = []
+ numbers.each do |number|
+ filtered << number if @sign == :positive and number > 0
+ filtered << number if @sign == :negative and number < 0
+ filtered << number if @sign == :non_negative and number >= 0
+ filtered << number if @sign == :non_positive and number <= 0
+ end
+ filtered
+ end
+
+ def & other
+ SectionFilter.new(self, other)
+ end
+
+ def | other
+ UnionFilter.new(self, other)
+ end
+end
+
+
+class TypeFilter
+ def initialize(type)
+ @type = type
+ end
+
+ def filter(numbers)
+ filtered = []
+ numbers.each do |number|
+ filtered << number if @type == :real and is_real?(number)
+ filtered << number if @type == :integer and number.is_a? Integer
+ filtered << number if @type == :complex and number.is_a? Complex
+ end
+ filtered
+ end
+
+ def is_real?(number)
+ number.is_a? Float or number.is_a? Rational
+ end
+
+ def & other
+ SectionFilter.new(self, other)
+ end
+
+ def | other
+ UnionFilter.new(self, other)
+ end
+end
+
+
+class SectionFilter
+ def initialize(first_filter, second_filter)
+ @first_filter = first_filter
+ @second_filter = second_filter
+ end
+
+ def filter(numbers)
+ @first_filter.filter(@second_filter.filter(numbers))
+ end
+end
+
+
+class UnionFilter
+ def initialize(first_filter, second_filter)
+ @first_filter = first_filter
+ @second_filter = second_filter
+ end
+
+ def filter(numbers)
+ result = @first_filter.filter(numbers)
+ @second_filter.filter(numbers).each do |number|
+ result << number
+ end
+ result
+ end
+end

Супер бързо си предал. Евала! Решението ти е добро.

Имам няколко коментара:

  • Слагай скоби около параметрите, когато дефинираш метод. Дори и при операторите. (Визирам <<, & и |)
  • Прегледай метода NumberSet#each и помисли каква е разликата между block.call number и yield number :)
  • Имам малък проблем с името SectionFilter. Може би, защото след UnionFilter очаквах да видя IntersectionFilter. Възможно е проблемът да е в мен.
  • Относно filter метода ти в TypeFilter и SignFilter, можеш да хвърлиш око на Enumerable#each_with_object

Помисли дали е възможно малко да ограничиш "знанието" на филтрите. Трябва ли да знаят за цялата колекция от числа? Помисли как работи Enumerable#select.

Успех :)

Емилиан обнови решението на 22.10.2014 17:37 (преди около 10 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
- def << number
+ def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@numbers = filter.filter(@numbers)
end
def each(&block)
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
- def & other
- SectionFilter.new(self, other)
+ def &(other)
+ IntersectionFilter.new(self, other)
end
- def | other
+ def |(other)
UnionFilter.new(self, other)
end
end
class SignFilter
def initialize(sign)
@sign = sign
end
def filter(numbers)
- filtered = []
- numbers.each do |number|
+ numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
- filtered
end
- def & other
- SectionFilter.new(self, other)
+ def &(other)
+ IntersectionFilter.new(self, other)
end
- def | other
+ def |(other)
UnionFilter.new(self, other)
end
end
class TypeFilter
def initialize(type)
@type = type
end
def filter(numbers)
- filtered = []
- numbers.each do |number|
+ numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
- filtered
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
- def & other
- SectionFilter.new(self, other)
+ def &(other)
+ IntersectionFilter.new(self, other)
end
- def | other
+ def |(other)
UnionFilter.new(self, other)
end
end
-class SectionFilter
+class IntersectionFilter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
class UnionFilter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end

Емилиан обнови решението на 22.10.2014 17:39 (преди около 10 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@numbers = filter.filter(@numbers)
end
def each(&block)
@numbers.each do |number|
- if block_given?
block.call number
- else
- yield number
- end
end
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class SignFilter
def initialize(sign)
@sign = sign
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class TypeFilter
def initialize(type)
@type = type
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class IntersectionFilter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
class UnionFilter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end

И аз благодаря за бързия feedback!

  • Сложих скобите при дефинирането на операторите.

  • Преименувах SectionFilter на IntersectionFilter (Съгласен съм, че е по-правилно така).

  • Преработих filter метода в TypeFilter и SignFilter да използва Enumerable#each_with_object.

Ако правилно съм разбрал block.call number е това което ми върши работа в момента, тъй като задължително искам да бъде подаден блок.

Сега ще поразмишлявам над последните препоръки. :smile:

Емилиан обнови решението на 23.10.2014 21:26 (преди около 10 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@numbers = filter.filter(@numbers)
end
def each(&block)
@numbers.each do |number|
block.call number
end
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
-class SignFilter
+class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
end
-
- def &(other)
- IntersectionFilter.new(self, other)
- end
-
- def |(other)
- UnionFilter.new(self, other)
- end
end
-class TypeFilter
+class TypeFilter < Filter
def initialize(type)
@type = type
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
-
- def &(other)
- IntersectionFilter.new(self, other)
- end
-
- def |(other)
- UnionFilter.new(self, other)
- end
end
-class IntersectionFilter
+class IntersectionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
-class UnionFilter
+class UnionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end

Емилиан обнови решението на 23.10.2014 21:39 (преди около 10 години)

class NumberSet
include Enumerable
- def initialize
- @numbers = []
+ def initialize(numbers = [])
+ @numbers = numbers
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
- @numbers = filter.filter(@numbers)
+ NumberSet.new(filter.filter(@numbers))
end
def each(&block)
@numbers.each do |number|
block.call number
end
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
end
class IntersectionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
class UnionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end

Емилиан обнови решението на 24.10.2014 14:06 (преди около 10 години)

class NumberSet
include Enumerable
def initialize(numbers = [])
@numbers = numbers
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
NumberSet.new(filter.filter(@numbers))
end
def each(&block)
- @numbers.each do |number|
- block.call number
- end
+ @numbers.each { |number| block.call number } if block_given?
+ @numbers.to_enum unless block_given?
end
end
class Filter
def initialize(&block)
@block = block
end
def filter(numbers)
numbers.select(&@block)
end
def &(other)
IntersectionFilter.new(self, other)
end
def |(other)
UnionFilter.new(self, other)
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @sign == :positive and number > 0
filtered << number if @sign == :negative and number < 0
filtered << number if @sign == :non_negative and number >= 0
filtered << number if @sign == :non_positive and number <= 0
end
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def filter(numbers)
numbers.each_with_object([]) do |number, filtered|
filtered << number if @type == :real and is_real?(number)
filtered << number if @type == :integer and number.is_a? Integer
filtered << number if @type == :complex and number.is_a? Complex
end
end
def is_real?(number)
number.is_a? Float or number.is_a? Rational
end
end
class IntersectionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
@first_filter.filter(@second_filter.filter(numbers))
end
end
class UnionFilter < Filter
def initialize(first_filter, second_filter)
@first_filter = first_filter
@second_filter = second_filter
end
def filter(numbers)
result = @first_filter.filter(numbers)
@second_filter.filter(numbers).each do |number|
result << number
end
result
end
end