Габриела обнови решението на 25.10.2014 10:43 (преди около 11 години)
+class NumberSet
+  include Enumerable
+
+  attr_accessor :numbers
+
+  def initialize
+    @numbers = []
+  end
+
+  def each(&block)
+    @numbers.each(&block)
+  end
+
+  def <<(element)
+    @numbers << element unless @numbers.include?(element)
+  end
+
+  def size
+    @numbers.size
+  end
+
+  def empty?
+    return true if @numbers.size == 0
+    false
+  end
+
+  def [](filter)
+    filtered_numbers = NumberSet.new
+    array = @numbers.select { |number| filter.matches? number }
+    array.each { |number| numbers << number }
+    filtered_numbers
+  end
+end
+
+class Filter
+  attr_accessor :filter
+
+  def initialize(&block)
+    @filter = block
+  end
+
+  def matches?(numbers)
+    @filter.(numbers)
+  end
+
+  def |(filter)
+    Filter.new { |number| matches? number or filter.matches? number }
+  end
+
+  def &(filter)
+    Filter.new { |number| matches? number and filter.matches? number }
+  end
+end
+
+class TypeFilter < Filter
+  attr_accessor :filter
+
+  def initialize(type)
+    if type == :integer
+      @filter = lambda { |number| number.is_a? Integer }
+    elsif type == :real
+      @filter = lambda { |number| number.is_a? Rational or number.is_a? Float}
+    else
+      @filter = lambda { |number| number.is_a? Complex }
+    end
+  end
+
+  def matches?(numbers)
+    @filter.(numbers)
+  end
+end
+
+class SignFilter < Filter
+  attr_accessor :filter
+
+  def initialize(sign)
+    @filter = lambda { |number| number > 0 }  if sign == :positive
+    @filter = lambda { |number| number <= 0 } if sign == :non_positive
+    @filter = lambda { |number| number < 0 }  if sign == :negative
+    @filter = lambda { |number| number >= 0 } if sign == :non_negative
+  end
+
+  def matches?(numbers)
+    @filter.(numbers)
+  end
+end
Здрасти,
Ето няколко неща, върху които можеш да помислиш:
- Защо параметъра на 
NumberSet#<<се казваelementпри положение, че навсякъде си ползвала по-яснотоnumber? - 
attr_accessor-ите не са ти нужни. - 
return true if @numbers.size == 0; falseе еквивалентно на@numbers.size == 0, което е еквивалентно на@numbers.empty?. Кой според теб е по-четимия вариант от трите? :) - Имаш typo в 
NumberSet#[].filtered_numbersседи празен. Можеш да погледнешEnumerable#each_with_object. - 
TypeFilterнаследяваFilter. Можеш да се възползваш от това и да напишешsuper() { |number| number.is_a? Integer }. Това ще подаде блок на конструктора наFilterи ще има същия ефект. Също така можеш да пробвашcaseвместоif/elsif/else. Същите неща важат заSignFilter. - 
Filter#matches?,TypeFIlter#matches?иSignFilter#matches?много си приличат. Кои два от тях можеш да махнеш без нещата да се счупят? :)) 
