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

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

Към профила на Светлозар Тодоров

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 15 успешни тест(а)
  • 9 неуспешни тест(а)

Код

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
def <<(new_number)
# Rational numbers preservation?
if !(new_number.is_a? Numeric) or @numbers.include? new_number
@numbers
else
@numbers.push(new_number)
@numbers
end
end
def size
each { |number| number = 1 }
.reduce(0) { |number| number = number + 1 }
end
def empty?
size > 0 ? false : true
end
def [](filter_type)
result = NumberSet.new
result = filter_type.extract(self)
end
end
class Filter
def initialize(&block)
@block = block
end
def extract(elements)
result = []
elements.each { |number| result << number if number == yield(number) }
end
def &(filter)
and_filter = -> { proc.call(self) && proc.call(filter) }
end
def |(filter)
or_filter = -> { proc.call(self) || proc.call(filter) }
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def determine_type
result = []
case @type
when :integer then result = ['Fixnum']
when :real then result = ['Float', 'Rational']
when :complex then result = ['Complex']
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_type.include? number.class.to_s
end
result
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def determine_sign
plus_infinity = 1.0 / 0.0
minus_infinity = -1.0 / 0.0
case @sign
when :positive then result = (0...plus_infinity)
when :non_positive then result = (minus_infinity..0)
when :negative then result = (minus_infinity...0)
when :non_negative then result = (0..plus_infinity)
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_sign.include? number
end
result
end
end

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

...........FF...FFFFFF.F

Failures:

  1) NumberSet can filter by custom filter
     Failure/Error: filtered_numbers = numbers[using]
     LocalJumpError:
       no block given (yield)
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:49:in `block in extract'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:10:in `call'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:10:in `block in each'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:8:in `each'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:8:in `each'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:49:in `extract'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:38:in `[]'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:61: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 filter positive numbers
     Failure/Error: expect(filtered_numbers.size).to eq expecting.size
       
       expected: 1
            got: 2
       
       (compared using ==)
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:180:in `can_filter'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:67: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)>'

  3) NumberSet can combine two filters with "and" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `extract' for #<Proc:0xb9478100>
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:38:in `[]'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:92: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)>'

  4) NumberSet can combine two filters with "or" rule
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `extract' for #<Proc:0xb938f658>
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:38:in `[]'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-1u2cw2u/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)>'

  5) NumberSet can combine multiple filters with "and" rule
     Failure/Error: filter        = non_negative & non_zero & mod_3_is_zero
     NoMethodError:
       undefined method `&' for #<Proc:0xb938eaa0>
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:108: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)>'

  6) NumberSet can combine multiple filters with "or" rule
     Failure/Error: filter        = even | negative | more_than_100
     NoMethodError:
       undefined method `|' for #<Proc:0xb938df24>
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:118: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)>'

  7) NumberSet can combine multiple filters with "and" and "or" rules
     Failure/Error: filter        = even & negative | mod_3_is_zero
     NoMethodError:
       undefined method `|' for #<Proc:0xb938d3f8>
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:128: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)>'

  8) NumberSet can combine multiple filters with "and", "or" and parenthesis
     Failure/Error: filtered_numbers = numbers[using]
     NoMethodError:
       undefined method `extract' for #<Proc:0xb938c7a0>
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:38:in `[]'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:179:in `can_filter'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:139: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)>'

  9) NumberSet returns enumerable of set's contents if no block is given to each
     Failure/Error: expect(numbers.each.to_a.size).to eq [1, 3, 5].size
     LocalJumpError:
       no block given (yield)
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:12:in `block in each'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:8:in `each'
     # /tmp/d20141028-18133-1u2cw2u/solution.rb:8:in `each'
     # /tmp/d20141028-18133-1u2cw2u/spec.rb:164: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.02176 seconds
24 examples, 9 failures

Failed examples:

rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:60 # NumberSet can filter by custom filter
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:66 # NumberSet can filter positive numbers
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:90 # NumberSet can combine two filters with "and" rule
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:97 # NumberSet can combine two filters with "or" rule
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:104 # NumberSet can combine multiple filters with "and" rule
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:114 # NumberSet can combine multiple filters with "or" rule
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:124 # NumberSet can combine multiple filters with "and" and "or" rules
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:134 # NumberSet can combine multiple filters with "and", "or" and parenthesis
rspec /tmp/d20141028-18133-1u2cw2u/spec.rb:159 # NumberSet returns enumerable of set's contents if no block is given to each

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

Светлозар обнови решението на 26.10.2014 20:06 (преди над 9 години)

+class NumberSet
+ include Enumerable
+ def initialize
+ @numbers = []
+ end
+
+ def each &block
+ @numbers.each do |number|
+ if block_given?
+ block.call number
+ else
+ yield number
+ end
+ end
+ end
+
+ def <<(new_number)
+ # Rational numbers preservation?
+ if !(new_number.is_a? Numeric) or @numbers.include? new_number
+ @numbers
+ else
+ @numbers.push(new_number)
+ @numbers
+ end
+ end
+
+ def size
+ each { |number| number = 1 }
+ .reduce(0) { |number| number = number + 1 }
+ end
+
+ def empty?
+ size > 0 ? false : true
+ end
+
+ def [](filter_type)
+ result = NumberSet.new
+ result = select yield(filter_type.extract_rule)
+ end
+end
+
+class Filter
+ def initialize(&block)
+ @block = block
+ end
+
+ def extract_rule
+ rule = @block
+ end
+
+ def &(filter)
+ end
+
+ def |(filter)
+ end
+end
+
+class TypeFilter < Filter
+ def initialize(type)
+ @type = type
+ end
+
+ def extract_rule
+ case @type
+ when :integer
+ then rule = Proc.new { |number| number.class == 'Integer' }
+ when :real
+ then rule = Proc.new { |number| number.class == 'Float' || 'Rational'}
+ when :complex
+ then rule = Proc.new { |number| number.class == 'Complex'}
+ end
+ rule
+ end
+end
+
+class SignFilter < Filter
+ def initialize(sign)
+ @sign = sign
+ end
+
+ def extract_rule
+ case @sign
+ when :positive then rule = Proc.new { |number| number > 0 }
+ when :non_positive then rule = Proc.new { |number| number <= 0 }
+ when :negative then rule = Proc.new { |number| number < 0 }
+ when :non_negative then rule = Proc.new { |number| number >= 0 }
+ end
+ rule
+ end
+end

Светлозар обнови решението на 27.10.2014 01:34 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
def <<(new_number)
# Rational numbers preservation?
if !(new_number.is_a? Numeric) or @numbers.include? new_number
@numbers
else
@numbers.push(new_number)
@numbers
end
end
def size
each { |number| number = 1 }
.reduce(0) { |number| number = number + 1 }
end
def empty?
size > 0 ? false : true
end
def [](filter_type)
result = NumberSet.new
- result = select yield(filter_type.extract_rule)
+ result = filter_type.extract(self)
end
end
class Filter
def initialize(&block)
@block = block
end
- def extract_rule
- rule = @block
+ def extract(elements)
+ result = []
+ elements.each { |number| result << number if number == yield(number) }
end
def &(filter)
end
def |(filter)
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
- def extract_rule
- case @type
- when :integer
- then rule = Proc.new { |number| number.class == 'Integer' }
- when :real
- then rule = Proc.new { |number| number.class == 'Float' || 'Rational'}
- when :complex
- then rule = Proc.new { |number| number.class == 'Complex'}
+ def determine_type
+ result = []
+ case @type
+ when :integer then result = ['Fixnum']
+ when :real then result = ['Float', 'Rational']
+ when :complex then result = ['Complex']
end
- rule
+ result
end
+
+ def extract(elements)
+ result = []
+ elements.each do |number|
+ result << number if determine_type.include? number.class.to_s
+ end
+ result
+ end
+
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
- def extract_rule
+ def determine_sign
+ plus_infinity = 1.0 / 0.0
+ minus_infinity = -1.0 / 0.0
case @sign
- when :positive then rule = Proc.new { |number| number > 0 }
- when :non_positive then rule = Proc.new { |number| number <= 0 }
- when :negative then rule = Proc.new { |number| number < 0 }
- when :non_negative then rule = Proc.new { |number| number >= 0 }
+ when :positive then result = (0...plus_infinity)
+ when :non_positive then result = (minus_infinity..0)
+ when :negative then result = (minus_infinity...0)
+ when :non_negative then result = (0..plus_infinity)
end
- rule
+ result
+ end
+
+ def extract(elements)
+ result = []
+ elements.each do |number|
+ result << number if determine_sign.include? number
+ end
+ result
end
end

Светлозар обнови решението на 27.10.2014 02:12 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
def <<(new_number)
# Rational numbers preservation?
if !(new_number.is_a? Numeric) or @numbers.include? new_number
@numbers
else
@numbers.push(new_number)
@numbers
end
end
def size
each { |number| number = 1 }
.reduce(0) { |number| number = number + 1 }
end
def empty?
size > 0 ? false : true
end
def [](filter_type)
result = NumberSet.new
result = filter_type.extract(self)
end
end
class Filter
def initialize(&block)
@block = block
+ @number = yield
end
def extract(elements)
result = []
- elements.each { |number| result << number if number == yield(number) }
+ elements.each { |number| result << number if number == @number }
end
def &(filter)
+ and_filter = -> { proc.call(self) && proc.call(filter)}
end
def |(filter)
+ and_filter = -> { proc.call(self) || proc.call(filter)}
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def determine_type
result = []
case @type
when :integer then result = ['Fixnum']
when :real then result = ['Float', 'Rational']
when :complex then result = ['Complex']
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_type.include? number.class.to_s
end
result
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def determine_sign
plus_infinity = 1.0 / 0.0
minus_infinity = -1.0 / 0.0
case @sign
when :positive then result = (0...plus_infinity)
when :non_positive then result = (minus_infinity..0)
when :negative then result = (minus_infinity...0)
when :non_negative then result = (0..plus_infinity)
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_sign.include? number
end
result
end
end

Светлозар обнови решението на 27.10.2014 02:14 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
def <<(new_number)
# Rational numbers preservation?
if !(new_number.is_a? Numeric) or @numbers.include? new_number
@numbers
else
@numbers.push(new_number)
@numbers
end
end
def size
each { |number| number = 1 }
.reduce(0) { |number| number = number + 1 }
end
def empty?
size > 0 ? false : true
end
def [](filter_type)
result = NumberSet.new
result = filter_type.extract(self)
end
end
class Filter
def initialize(&block)
@block = block
@number = yield
end
def extract(elements)
result = []
elements.each { |number| result << number if number == @number }
end
def &(filter)
- and_filter = -> { proc.call(self) && proc.call(filter)}
+ and_filter = -> { proc.call(self) && proc.call(filter) }
end
def |(filter)
- and_filter = -> { proc.call(self) || proc.call(filter)}
+ or_filter = -> { proc.call(self) || proc.call(filter) }
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def determine_type
result = []
case @type
when :integer then result = ['Fixnum']
when :real then result = ['Float', 'Rational']
when :complex then result = ['Complex']
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_type.include? number.class.to_s
end
result
end
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def determine_sign
plus_infinity = 1.0 / 0.0
minus_infinity = -1.0 / 0.0
case @sign
when :positive then result = (0...plus_infinity)
when :non_positive then result = (minus_infinity..0)
when :negative then result = (minus_infinity...0)
when :non_negative then result = (0..plus_infinity)
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_sign.include? number
end
result
end
end

Светлозар обнови решението на 27.10.2014 02:34 (преди над 9 години)

class NumberSet
include Enumerable
def initialize
@numbers = []
end
def each &block
@numbers.each do |number|
if block_given?
block.call number
else
yield number
end
end
end
def <<(new_number)
# Rational numbers preservation?
if !(new_number.is_a? Numeric) or @numbers.include? new_number
@numbers
else
@numbers.push(new_number)
@numbers
end
end
def size
each { |number| number = 1 }
.reduce(0) { |number| number = number + 1 }
end
def empty?
size > 0 ? false : true
end
def [](filter_type)
result = NumberSet.new
result = filter_type.extract(self)
end
end
class Filter
def initialize(&block)
@block = block
- @number = yield
end
def extract(elements)
result = []
- elements.each { |number| result << number if number == @number }
+ elements.each { |number| result << number if number == yield(number) }
end
def &(filter)
and_filter = -> { proc.call(self) && proc.call(filter) }
end
def |(filter)
or_filter = -> { proc.call(self) || proc.call(filter) }
end
end
class TypeFilter < Filter
def initialize(type)
@type = type
end
def determine_type
result = []
case @type
when :integer then result = ['Fixnum']
when :real then result = ['Float', 'Rational']
when :complex then result = ['Complex']
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_type.include? number.class.to_s
end
result
end
-
end
class SignFilter < Filter
def initialize(sign)
@sign = sign
end
def determine_sign
plus_infinity = 1.0 / 0.0
minus_infinity = -1.0 / 0.0
case @sign
when :positive then result = (0...plus_infinity)
when :non_positive then result = (minus_infinity..0)
when :negative then result = (minus_infinity...0)
when :non_negative then result = (0..plus_infinity)
end
result
end
def extract(elements)
result = []
elements.each do |number|
result << number if determine_sign.include? number
end
result
end
end
  • Слагай празен ред между include-и и дефиницията на методи за по-добра четимост.
  • Имплементацията ти на each е преоткриване на колелото. Можеше да вземеш блока в NumberSet#each и да го предадеш на Array#each. Същото важи за NumberSet#size и NumberSet#empty?.
  • yield работи върху блока, подаден на текущия метод. За Filter#extract няма такъв. Какво трябва да прави proc.call(self). Експериментирай малко, не прави предположения.
  • По-добре е филтрите да отговарят за дадено число, а не да филтрират всичко. Ако ще трябва да филтрират всичко следва да връщат NumberSet-и, а не масиви. В момента вземаш имена на класове като низове и ги сравняваш, което си е хакария, също това с безкрайността е забавно, но е work around. TypeFilter#extract и SignFilter#extract са почти едно и също нещо, което не е ok.
  • Няма смисъл да присвояваш на променлива нещото, което връщаш на същия ред. Какво връщат сегашните Filter#& и Filter#|? Има и конвенция за имената, когато предефинираш оператор с два операнда.
  • В 99% от случаите result е лошо име за променлива. Или трябва да измислиш друго, или друга имплементация. Навсякъде тук съществува алтернатива.
  • Не се грижи за невалидни входни данни (new_number.is_a? Numeric).

Благодаря за коментарите!

Съжалявам, че по-рано не успях да я пусна за проверка. :disappointed:

Няма да ми остане време да я пратя коригирана до крайния срок, но непременно ще погледна по-късно, ще помисля отново върху забележките и ще нанеса поправките.