Делян обнови решението на 27.10.2014 15:12 (преди около 10 години)
+class NumberSet
+ include Enumerable
+
+ def initialize
+ @numbers = []
+ end
+
+ def <<(number)
+ if not contains_number?(number)
+ @numbers << number
+ end
+ end
+
+ def [](filter)
+ filter_matches = @numbers.select { |number| filter.is_match? number }
+ NumberSet.new.merge filter_matches
+ end
+
+ def merge(array)
+ array.each { |number| @numbers << number }
+ end
+
+ def size
+ @numbers.size
+ end
+
+ def empty?
+ @numbers.size === 0
+ end
+
+ def each
+ @numbers.each { |number| yield number }
+ end
+
+ private
+
+ def contains_number?(number)
+ @numbers.any? { |current_number| number == current_number }
+ end
+end
+
+class Filter
+ def initialize(&block)
+ @block = block
+ end
+
+ def is_match?(number)
+ @block.call number
+ end
+
+ def &(other)
+ Filter.new { |number| self.is_match? number and other.is_match? number }
+ end
+
+ def |(other)
+ Filter.new { |number| self.is_match? number or other.is_match? number }
+ end
+end
+
+class TypeFilter < Filter
+ @@types = {
+ integer: Integer,
+ real: Float,
+ complex: Complex,
+ }
+
+ def initialize(type)
+ type = @@types.fetch type
+ super() { |number| number.is_a? type }
+ end
+end
+
+class SignFilter < Filter
+ @@sign_filters = {
+ positive: Proc.new { |number| number > 0 },
+ negative: Proc.new { |number| number < 0 },
+ non_negative: Proc.new { |number| number >= 0 },
+ non_positive: Proc.new { |number| number <= 0 },
+ }
+
+ def initialize(sign)
+ sign_filter = @@sign_filters.fetch(sign)
+ super(&sign_filter)
+ end
+end