Решение на Втора задача от Йоана Тодорова

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

Към профила на Йоана Тодорова

Резултати

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

Код

class NumberSet
include Enumerable
def initialize
@set = []
end
def each
return to_enum(:each) unless block_given?
@set.each { |number| yield number }
end
def <<(number)
@set << number unless @set.include? number
self
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
NumberSet.new.tap do |number_set|
each { |number| filter.persists?(number) && number_set << number }
end
end
end
class Filter
def initialize(&block)
@block = block
end
def persists?(number)
@block.call(number)
end
def &(other)
Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
@block = case type
when :integer then Proc.new { |number| number.is_a?(Integer) }
when :complex then Proc.new { |number| number.is_a?(Complex) }
else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
end
end
end
class SignFilter < Filter
def initialize(sign)
@block = case sign
when :positive then Proc.new { |number| number > 0 }
when :non_positive then Proc.new { |number| number <= 0 }
when :negative then Proc.new { |number| number < 0 }
when :non_negative then Proc.new { |number| number >= 0 }
end
end
end

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

........................

Finished in 0.02206 seconds
24 examples, 0 failures

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

Йоана обнови решението на 23.10.2014 21:40 (преди над 9 години)

+class NumberSet
+ include Enumerable
+
+ def initialize
+ @set = []
+ end
+
+ def each(&block)
+ @set.each &block
+ end
+
+ def <<(new_number)
+ @set.none? { |number| number == new_number } && @set << new_number
+ end
+
+ def size
+ @set.size
+ end
+
+ def empty?
+ @set.empty?
+ end
+
+ def [](block)
+ @set.select { |number| block.call(number) }
+ end
+end
+
+class BaseFilter
+ def initialize(&block)
+ @block = block
+ end
+
+ def call(number)
+ @block.call(number)
+ end
+
+ def &(other)
+ BaseFilter.new do |number|
+ call(number) && other.call(number)
+ end
+ end
+
+ def |(other)
+ BaseFilter.new do |number|
+ call(number) || other.call(number)
+ end
+ end
+end
+
+class Filter < BaseFilter
+end
+
+class TypeFilter < BaseFilter
+ def initialize(type)
+ @block = send(type)
+ end
+
+ private
+
+ def integer
+ Proc.new { |number| number.is_a? Integer }
+ end
+
+ def real
+ Proc.new { |number| number.is_a?(Float) || number.is_a?(Rational) }
+ end
+
+ def complex
+ Proc.new { |number| number.is_a? Complex }
+ end
+end
+
+class SignFilter < BaseFilter
+ def initialize(sign)
+ @block = send(sign)
+ end
+
+ private
+
+ def positive
+ Proc.new { |number| number > 0 }
+ end
+
+ def non_positive
+ Proc.new { |number| number <= 0 }
+ end
+
+ def negative
+ Proc.new { |number| number < 0 }
+ end
+
+ def non_negative
+ Proc.new { |number| number >= 0 }
+ end
+end

Йоана обнови решението на 23.10.2014 21:54 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each &block
end
def <<(new_number)
@set.none? { |number| number == new_number } && @set << new_number
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](block)
@set.select { |number| block.call(number) }
end
end
class BaseFilter
def initialize(&block)
@block = block
end
def call(number)
@block.call(number)
end
def &(other)
- BaseFilter.new do |number|
- call(number) && other.call(number)
- end
+ BaseFilter.new { |number| call(number) && other.call(number) }
end
def |(other)
- BaseFilter.new do |number|
- call(number) || other.call(number)
- end
+ BaseFilter.new { |number| call(number) || other.call(number) }
end
end
class Filter < BaseFilter
end
class TypeFilter < BaseFilter
def initialize(type)
@block = send(type)
end
private
def integer
Proc.new { |number| number.is_a? Integer }
end
def real
Proc.new { |number| number.is_a?(Float) || number.is_a?(Rational) }
end
def complex
Proc.new { |number| number.is_a? Complex }
end
end
class SignFilter < BaseFilter
- def initialize(sign)
- @block = send(sign)
- end
+ OPERATORS = {
+ positive: :> ,
+ non_positive: :<= ,
+ negative: :< ,
+ non_negative: :>=
+ }
- private
-
- def positive
- Proc.new { |number| number > 0 }
- end
-
- def non_positive
- Proc.new { |number| number <= 0 }
- end
-
- def negative
- Proc.new { |number| number < 0 }
- end
-
- def non_negative
- Proc.new { |number| number >= 0 }
+ def initialize(sign)
+ @block = Proc.new { |number| number.send(OPERATORS[sign], 0) }
end
end

Йоана обнови решението на 24.10.2014 10:10 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
- @set.each &block
+ @set.each(&block)
end
def <<(new_number)
@set.none? { |number| number == new_number } && @set << new_number
end
def size
@set.size
end
def empty?
@set.empty?
end
- def [](block)
- @set.select { |number| block.call(number) }
+ def [](filter)
+ @set.select { |number| filter.call(number) }
end
end
class BaseFilter
def initialize(&block)
@block = block
end
def call(number)
@block.call(number)
end
def &(other)
BaseFilter.new { |number| call(number) && other.call(number) }
end
def |(other)
BaseFilter.new { |number| call(number) || other.call(number) }
end
end
class Filter < BaseFilter
end
class TypeFilter < BaseFilter
- def initialize(type)
- @block = send(type)
- end
+ TYPES = {
+ integer: [Integer],
+ real: [Float, Rational],
+ complex: [Complex]
+ }
- private
-
- def integer
- Proc.new { |number| number.is_a? Integer }
- end
-
- def real
- Proc.new { |number| number.is_a?(Float) || number.is_a?(Rational) }
- end
-
- def complex
- Proc.new { |number| number.is_a? Complex }
+ def initialize(type)
+ @block = Proc.new do |number|
+ TYPES[type].reduce(false) { |memo, type| memo || number.is_a?(type) }
+ end
end
end
class SignFilter < BaseFilter
OPERATORS = {
positive: :> ,
non_positive: :<= ,
negative: :< ,
non_negative: :>=
}
def initialize(sign)
@block = Proc.new { |number| number.send(OPERATORS[sign], 0) }
end
end

Йоана обнови решението на 24.10.2014 13:33 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each(&block)
end
def <<(new_number)
@set.none? { |number| number == new_number } && @set << new_number
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
@set.select { |number| filter.call(number) }
end
end
class BaseFilter
def initialize(&block)
@block = block
end
def call(number)
@block.call(number)
end
def &(other)
BaseFilter.new { |number| call(number) && other.call(number) }
end
def |(other)
BaseFilter.new { |number| call(number) || other.call(number) }
end
end
class Filter < BaseFilter
end
class TypeFilter < BaseFilter
TYPES = {
+ real: [Float, Rational],
integer: [Integer],
- real: [Float, Rational],
complex: [Complex]
}
def initialize(type)
@block = Proc.new do |number|
TYPES[type].reduce(false) { |memo, type| memo || number.is_a?(type) }
end
end
end
class SignFilter < BaseFilter
OPERATORS = {
- positive: :> ,
+ positive: :> ,
+ negative: :< ,
non_positive: :<= ,
- negative: :< ,
non_negative: :>=
}
def initialize(sign)
@block = Proc.new { |number| number.send(OPERATORS[sign], 0) }
end
end

Здрасти

Имам няколко забележки. На места кодът, който си написала е твърде "хитър". Според мен ще е много по-просто и лесно за разбиране, ако се придържаш към по-прости конструкции. Без много динамични(магически) извиквания, където не се налага.

  • @set.none? { |number| number == new_number } е еквивалентно на not @set.include? new_number
  • NumberSet#[] трябва да връща NumberSet обект. В момента връщаш Array обект.
  • Защо ти е BaseFilter? Според мен можеш да го слееш с Filter.
  • Можеш ли да измислиш по-добро име за BaseFilter#call. До колкото виждам връща булева стойност, а ние имаме конвенция за такива методи. Също гледай да съобразиш какво точно прави метода и да го изразиш максимално ясно в името му! :)
  • Този reduce в TypeFilter#initialize ме обърква. Не можеше ли да е просто case с отделните варианти?
  • Защо send?? :D Този код е твърде "хитър". Давай с case на различните варианти.

Успех. :))

Йоана обнови решението на 25.10.2014 10:48 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each(&block)
end
- def <<(new_number)
- @set.none? { |number| number == new_number } && @set << new_number
+ def <<(number)
+ ! @set.include?(number) && @set << number
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
- @set.select { |number| filter.call(number) }
+ @set.select { |number| filter.persists?(number) }
end
end
-class BaseFilter
+class Filter
def initialize(&block)
@block = block
end
- def call(number)
+ def persists?(number)
@block.call(number)
end
def &(other)
- BaseFilter.new { |number| call(number) && other.call(number) }
+ Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
- BaseFilter.new { |number| call(number) || other.call(number) }
+ Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
-class Filter < BaseFilter
-end
-
-class TypeFilter < BaseFilter
- TYPES = {
- real: [Float, Rational],
- integer: [Integer],
- complex: [Complex]
- }
-
+class TypeFilter < Filter
def initialize(type)
- @block = Proc.new do |number|
- TYPES[type].reduce(false) { |memo, type| memo || number.is_a?(type) }
- end
+ @block = case type
+ when :integer then Proc.new { |number| number.is_a?(Integer) }
+ when :complex then Proc.new { |number| number.is_a?(Complex) }
+ else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
+ end
end
end
-class SignFilter < BaseFilter
- OPERATORS = {
- positive: :> ,
- negative: :< ,
- non_positive: :<= ,
- non_negative: :>=
- }
-
+class SignFilter < Filter
def initialize(sign)
- @block = Proc.new { |number| number.send(OPERATORS[sign], 0) }
+ @block = case sign
+ when :positive then Proc.new { |number| number > 0 }
+ when :non_positive then Proc.new { |number| number <= 0 }
+ when :negative then Proc.new { |number| number < 0 }
+ when :non_negative then Proc.new { |number| number >= 0 }
+ end
end
end

Йоана обнови решението на 25.10.2014 10:54 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each(&block)
end
def <<(number)
! @set.include?(number) && @set << number
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
- @set.select { |number| filter.persists?(number) }
+ NumberSet.new.tap do |number_set|
+ @set.each { |number| filter.persists?(number) && number_set << number }
+ end
end
end
class Filter
def initialize(&block)
@block = block
end
def persists?(number)
@block.call(number)
end
def &(other)
Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
@block = case type
when :integer then Proc.new { |number| number.is_a?(Integer) }
when :complex then Proc.new { |number| number.is_a?(Complex) }
else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
end
end
end
class SignFilter < Filter
def initialize(sign)
@block = case sign
when :positive then Proc.new { |number| number > 0 }
when :non_positive then Proc.new { |number| number <= 0 }
when :negative then Proc.new { |number| number < 0 }
when :non_negative then Proc.new { |number| number >= 0 }
end
end
end

Йоана обнови решението на 25.10.2014 11:14 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each(&block)
end
def <<(number)
! @set.include?(number) && @set << number
+ self
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
NumberSet.new.tap do |number_set|
@set.each { |number| filter.persists?(number) && number_set << number }
end
end
end
class Filter
def initialize(&block)
@block = block
end
def persists?(number)
@block.call(number)
end
def &(other)
Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
@block = case type
when :integer then Proc.new { |number| number.is_a?(Integer) }
when :complex then Proc.new { |number| number.is_a?(Complex) }
else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
end
end
end
class SignFilter < Filter
def initialize(sign)
@block = case sign
when :positive then Proc.new { |number| number > 0 }
when :non_positive then Proc.new { |number| number <= 0 }
when :negative then Proc.new { |number| number < 0 }
when :non_negative then Proc.new { |number| number >= 0 }
end
end
end

Йоана обнови решението на 26.10.2014 11:51 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
def each(&block)
@set.each(&block)
end
def <<(number)
- ! @set.include?(number) && @set << number
+ @set << number unless @set.include? number
self
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
NumberSet.new.tap do |number_set|
@set.each { |number| filter.persists?(number) && number_set << number }
end
end
end
class Filter
def initialize(&block)
@block = block
end
def persists?(number)
@block.call(number)
end
def &(other)
Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
@block = case type
when :integer then Proc.new { |number| number.is_a?(Integer) }
when :complex then Proc.new { |number| number.is_a?(Complex) }
else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
end
end
end
class SignFilter < Filter
def initialize(sign)
@block = case sign
when :positive then Proc.new { |number| number > 0 }
when :non_positive then Proc.new { |number| number <= 0 }
when :negative then Proc.new { |number| number < 0 }
when :non_negative then Proc.new { |number| number >= 0 }
end
end
end

Нашата версия на ръководството по стил препоръчва идентиране с едно ниво навътре на when клаузите на case. И на мен ми се струва по-четимо с отместване навътре, така че препоръчвам да го промениш по този начин.

Йоана обнови решението на 26.10.2014 14:20 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@set = []
end
- def each(&block)
- @set.each(&block)
+ def each
+ return to_enum(:each) unless block_given?
+ @set.each { |number| yield number }
end
def <<(number)
@set << number unless @set.include? number
self
end
def size
@set.size
end
def empty?
@set.empty?
end
def [](filter)
NumberSet.new.tap do |number_set|
- @set.each { |number| filter.persists?(number) && number_set << number }
+ each { |number| filter.persists?(number) && number_set << number }
end
end
end
class Filter
def initialize(&block)
@block = block
end
def persists?(number)
@block.call(number)
end
def &(other)
Filter.new { |number| persists?(number) && other.persists?(number) }
end
def |(other)
Filter.new { |number| persists?(number) || other.persists?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
@block = case type
- when :integer then Proc.new { |number| number.is_a?(Integer) }
- when :complex then Proc.new { |number| number.is_a?(Complex) }
- else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
+ when :integer then Proc.new { |number| number.is_a?(Integer) }
+ when :complex then Proc.new { |number| number.is_a?(Complex) }
+ else Proc.new { |n| n.is_a?(Float) || n.is_a?(Rational) }
end
end
end
class SignFilter < Filter
def initialize(sign)
@block = case sign
- when :positive then Proc.new { |number| number > 0 }
- when :non_positive then Proc.new { |number| number <= 0 }
- when :negative then Proc.new { |number| number < 0 }
- when :non_negative then Proc.new { |number| number >= 0 }
+ when :positive then Proc.new { |number| number > 0 }
+ when :non_positive then Proc.new { |number| number <= 0 }
+ when :negative then Proc.new { |number| number < 0 }
+ when :non_negative then Proc.new { |number| number >= 0 }
end
end
end