Решение на Втора задача от Явор Михайлов

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

Към профила на Явор Михайлов

Резултати

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

Код

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each(&block)
@numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@filtered_number_set = NumberSet.new
@numbers.each do |number|
@filtered_number_set << number if filter.validate(number)
end
@filtered_number_set
end
end
class Filter
attr_accessor :block
def initialize(&block)
@block = block
end
def &(other)
Filter.new { |number| validate(number) and other.validate(number) }
end
def |(other)
Filter.new { |number| validate(number) or other.validate(number) }
end
def validate(number)
block.call(number)
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
@block = case type_of_filter
when :complex then ->(number) { number.is_a? Complex }
when :integer then ->(number) { number.is_a? Integer }
when :real
lambda do |number|
number.is_a? Float or number.is_a? Rational
end
end
end
end
class SignFilter < Filter
def initialize(type_of_filter)
@block = case type_of_filter
when :positive then ->(number) { number > 0 }
when :non_positive then ->(number) { number <= 0 }
when :negative then ->(number) { number < 0 }
when :non_negative then ->(number) { number >= 0 }
end
end
end

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

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

Finished in 0.02245 seconds
24 examples, 0 failures

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

Явор обнови решението на 24.10.2014 04:00 (преди над 9 години)

+class NumberSet
+ include Enumerable
+
+ def initialize
+ @numbers = []
+ end
+
+ def <<(value)
+ @numbers << value unless @numbers.include?(value)
+ end
+
+ def each
+ if block_given?
+ @numbers.each { |number| yield number }
+ else
+ @numbers.each
+ end
+ end
+
+ def size
+ @numbers.size
+ end
+
+ def empty?
+ @numbers.empty?
+ end
+
+ def [](filter)
+ filtered_array = []
+
+ filter.blocks.each do |current_filter|
+ filtered_array << @numbers.select(&current_filter)
+ end
+
+ filtered_array.reduce(&:&)
+ end
+end
+
+class Filter
+ attr_accessor :blocks
+
+ def initialize(&block)
+ @blocks = []
+ @blocks << block if block_given?
+ end
+
+ def &(other)
+ new_filter = Filter.new
+ new_filter.blocks = @blocks.concat(other.blocks)
+ new_filter
+ end
+end
+
+class TypeFilter < Filter
+ def initialize(type_of_filter)
+ @blocks = []
+
+ block = ->(n) { n.is_a? Complex } if type_of_filter == :complex
+ block = ->(n) { n.is_a? Integer } if type_of_filter == :integer
+ if type_of_filter == :real
+ block = ->(n) { n.is_a? Float or n.is_a? Rational }
+ end
+
+ @blocks << block
+ end
+end
+
+class SignFilter < Filter
+ def initialize(type_of_filter)
+ block = ->(n) { n > 0 } if type_of_filter == :positive
+ block = ->(n) { n <= 0 } if type_of_filter == :non_positive
+ block = ->(n) { n < 0 } if type_of_filter == :negative
+ block = ->(n) { n >= 0 } if type_of_filter == :non_negative
+
+ @blocks = []
+ @blocks << block
+ end
+end

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

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each
if block_given?
@numbers.each { |number| yield number }
else
@numbers.each
end
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
filtered_array = []
filter.blocks.each do |current_filter|
filtered_array << @numbers.select(&current_filter)
end
- filtered_array.reduce(&:&)
+ filtered_number_set = NumberSet.new
+ filtered_array.reduce(&:&).each { |n| filtered_number_set << n }
+ filtered_number_set
end
end
class Filter
attr_accessor :blocks
def initialize(&block)
@blocks = []
@blocks << block if block_given?
end
def &(other)
new_filter = Filter.new
new_filter.blocks = @blocks.concat(other.blocks)
new_filter
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
@blocks = []
block = ->(n) { n.is_a? Complex } if type_of_filter == :complex
block = ->(n) { n.is_a? Integer } if type_of_filter == :integer
if type_of_filter == :real
block = ->(n) { n.is_a? Float or n.is_a? Rational }
end
@blocks << block
end
end
class SignFilter < Filter
def initialize(type_of_filter)
block = ->(n) { n > 0 } if type_of_filter == :positive
block = ->(n) { n <= 0 } if type_of_filter == :non_positive
block = ->(n) { n < 0 } if type_of_filter == :negative
block = ->(n) { n >= 0 } if type_of_filter == :non_negative
@blocks = []
@blocks << block
end
end

Здрасти,

Имам два коментара/въпроса на този етап.

  • Няма ли по-як начин да се напише тоя NumberSet#each? Пробвай да вземеш блока като параметър.
  • Какво налага съществуването на масива @blocks във филтрите ти? Ако пазиш филтрите така заради & и | методите, пробвай друг подход. Можеш да имаш метод във филтрите, който "изпълнява" филтъра за число и на базата на резултата от този метод да преценяш дали число "минава" филтъра. Какво мислиш?

Явор обнови решението на 25.10.2014 22:30 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
- def each
- if block_given?
- @numbers.each { |number| yield number }
- else
- @numbers.each
- end
+ def each(&block)
+ @numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
- filtered_array = []
+ @filtered_numbers = NumberSet.new
- filter.blocks.each do |current_filter|
- filtered_array << @numbers.select(&current_filter)
+ @numbers.each do |number|
+ @filtered_numbers << number if filter.filter(number)
end
- filtered_number_set = NumberSet.new
- filtered_array.reduce(&:&).each { |n| filtered_number_set << n }
- filtered_number_set
+ @filtered_numbers
end
end
class Filter
- attr_accessor :blocks
+ attr_accessor :block
def initialize(&block)
- @blocks = []
- @blocks << block if block_given?
+ @block = block
end
def &(other)
- new_filter = Filter.new
- new_filter.blocks = @blocks.concat(other.blocks)
- new_filter
+ Filter.new { |n| filter(n) and other.filter(n) }
end
+
+ def |(other)
+ Filter.new { |n| filter(n) or other.filter(n) }
+ end
+
+ def filter(number)
+ block.call(number)
+ end
end
class TypeFilter < Filter
def initialize(type_of_filter)
- @blocks = []
-
block = ->(n) { n.is_a? Complex } if type_of_filter == :complex
block = ->(n) { n.is_a? Integer } if type_of_filter == :integer
+
if type_of_filter == :real
block = ->(n) { n.is_a? Float or n.is_a? Rational }
end
- @blocks << block
+ @block = block
end
end
class SignFilter < Filter
def initialize(type_of_filter)
block = ->(n) { n > 0 } if type_of_filter == :positive
block = ->(n) { n <= 0 } if type_of_filter == :non_positive
block = ->(n) { n < 0 } if type_of_filter == :negative
block = ->(n) { n >= 0 } if type_of_filter == :non_negative
- @blocks = []
- @blocks << block
+ @block = block
end
-end
+end

Здрасти. Благодаря за коментарите.

  • NumberSet#each го оправих, всъшност и преди го бях написал така, но видях метода block_given? и реших да потърся място, където мога да го използвам ;).
  • Всъшност, когато си предадох домашното, все още не бях измислил как ще стане | оператора. Това от което щях да тръгна е да сменям filtered_array.reduce(&:&) на filtered_array.reduce(&:|), което сега разбирам каква лоша идея е било. Голямо благодарско за предложението с метода, който приема число.

Явор обнови решението на 25.10.2014 22:55 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each(&block)
@numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
- @filtered_numbers = NumberSet.new
+ @filtered_number_set = NumberSet.new
@numbers.each do |number|
- @filtered_numbers << number if filter.filter(number)
+ @filtered_number_set << number if filter.validate(number)
end
- @filtered_numbers
+ @filtered_number_set
end
end
class Filter
attr_accessor :block
def initialize(&block)
@block = block
end
def &(other)
- Filter.new { |n| filter(n) and other.filter(n) }
+ Filter.new { |number| validate(number) and other.validate(number) }
end
def |(other)
- Filter.new { |n| filter(n) or other.filter(n) }
+ Filter.new { |number| validate(number) or other.validate(number) }
end
- def filter(number)
+ def validate(number)
block.call(number)
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
- block = ->(n) { n.is_a? Complex } if type_of_filter == :complex
- block = ->(n) { n.is_a? Integer } if type_of_filter == :integer
+ block = ->(number) { number.is_a? Complex } if type_of_filter == :complex
+ block = ->(number) { number.is_a? Integer } if type_of_filter == :integer
if type_of_filter == :real
- block = ->(n) { n.is_a? Float or n.is_a? Rational }
+ block = ->(number) { number.is_a? Float or number.is_a? Rational }
end
@block = block
end
end
class SignFilter < Filter
def initialize(type_of_filter)
- block = ->(n) { n > 0 } if type_of_filter == :positive
- block = ->(n) { n <= 0 } if type_of_filter == :non_positive
- block = ->(n) { n < 0 } if type_of_filter == :negative
- block = ->(n) { n >= 0 } if type_of_filter == :non_negative
+ block = ->(number) { number > 0 } if type_of_filter == :positive
+ block = ->(number) { number <= 0 } if type_of_filter == :non_positive
+ block = ->(number) { number < 0 } if type_of_filter == :negative
+ block = ->(number) { number >= 0 } if type_of_filter == :non_negative
@block = block
end
end

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

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each(&block)
@numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@filtered_number_set = NumberSet.new
@numbers.each do |number|
@filtered_number_set << number if filter.validate(number)
end
@filtered_number_set
end
end
class Filter
attr_accessor :block
def initialize(&block)
@block = block
end
def &(other)
Filter.new { |number| validate(number) and other.validate(number) }
end
def |(other)
Filter.new { |number| validate(number) or other.validate(number) }
end
def validate(number)
block.call(number)
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
- block = ->(number) { number.is_a? Complex } if type_of_filter == :complex
- block = ->(number) { number.is_a? Integer } if type_of_filter == :integer
-
- if type_of_filter == :real
- block = ->(number) { number.is_a? Float or number.is_a? Rational }
- end
-
- @block = block
+ @block = case type_of_filter
+ when :complex then block = ->(number) { number.is_a? Complex }
+ when :integer then block = ->(number) { number.is_a? Integer }
+ when :real
+ ->(number) do
+ number.is_a? Float or number.is_a? Rational
+ end
+ end
end
end
class SignFilter < Filter
def initialize(type_of_filter)
- block = ->(number) { number > 0 } if type_of_filter == :positive
- block = ->(number) { number <= 0 } if type_of_filter == :non_positive
- block = ->(number) { number < 0 } if type_of_filter == :negative
- block = ->(number) { number >= 0 } if type_of_filter == :non_negative
-
- @block = block
+ @block = case type_of_filter
+ when :positive then ->(number) { number > 0 }
+ when :non_positive then ->(number) { number <= 0 }
+ when :negative then ->(number) { number < 0 }
+ when :non_negative then ->(number) { number >= 0 }
+ end
end
end

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

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each(&block)
@numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@filtered_number_set = NumberSet.new
@numbers.each do |number|
@filtered_number_set << number if filter.validate(number)
end
@filtered_number_set
end
end
class Filter
attr_accessor :block
def initialize(&block)
@block = block
end
def &(other)
Filter.new { |number| validate(number) and other.validate(number) }
end
def |(other)
Filter.new { |number| validate(number) or other.validate(number) }
end
def validate(number)
block.call(number)
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
@block = case type_of_filter
- when :complex then block = ->(number) { number.is_a? Complex }
- when :integer then block = ->(number) { number.is_a? Integer }
+ when :complex then ->(number) { number.is_a? Complex }
+ when :integer then ->(number) { number.is_a? Integer }
when :real
->(number) do
number.is_a? Float or number.is_a? Rational
end
end
end
end
class SignFilter < Filter
def initialize(type_of_filter)
@block = case type_of_filter
when :positive then ->(number) { number > 0 }
when :non_positive then ->(number) { number <= 0 }
when :negative then ->(number) { number < 0 }
when :non_negative then ->(number) { number >= 0 }
end
end
-end
+end

Така по-добре ли е? Бях забравил за думичката then и без нея ми се чупеше skeptic-а. Case-а добре ли е идентиран така, при положение, че се присвоява? Rubocop ми казва, че когато имам multiline lambda, да използвам lambda, а не ->. Тоест:


# Bad
->(number) do
 number.is_a? Float or number.is_a? Rational
end

# Good
lambda do |number|
 number.is_a? Float or number.is_a? Rational
end

Да се съобразя ли с тази конвенция? Според style guide-a от bbatsov, първото изглежда "extremely awkward".

Благодаря :)

Явор обнови решението на 27.10.2014 16:37 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def <<(value)
@numbers << value unless @numbers.include?(value)
end
def each(&block)
@numbers.each(&block)
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
@filtered_number_set = NumberSet.new
@numbers.each do |number|
@filtered_number_set << number if filter.validate(number)
end
@filtered_number_set
end
end
class Filter
attr_accessor :block
def initialize(&block)
@block = block
end
def &(other)
Filter.new { |number| validate(number) and other.validate(number) }
end
def |(other)
Filter.new { |number| validate(number) or other.validate(number) }
end
def validate(number)
block.call(number)
end
end
class TypeFilter < Filter
def initialize(type_of_filter)
- @block = case type_of_filter
+ @block = case type_of_filter
when :complex then ->(number) { number.is_a? Complex }
when :integer then ->(number) { number.is_a? Integer }
when :real
- ->(number) do
+ lambda do |number|
number.is_a? Float or number.is_a? Rational
end
- end
+ end
end
end
class SignFilter < Filter
def initialize(type_of_filter)
- @block = case type_of_filter
+ @block = case type_of_filter
when :positive then ->(number) { number > 0 }
when :non_positive then ->(number) { number <= 0 }
when :negative then ->(number) { number < 0 }
when :non_negative then ->(number) { number >= 0 }
- end
+ end
end
-end
+end