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

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

Към профила на Мая Терзиева

Резултати

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

Код

class NumberSet
include Enumerable
def initialize(numbers = [])
@numbers = numbers.uniq
end
def <<(number)
@numbers << number unless @numbers.include? number
end
def each(&operation)
@numbers.each &operation
end
def size
@numbers.size
end
def empty?
@numbers.empty?
end
def [](filter)
NumberSet.new @numbers.select { |number| filter.include?(number) }
end
end
class Filter
def initialize(&criterion)
@criterion = criterion
end
def include?(number)
@criterion.call number
end
def &(other)
Filter.new { |number| include?(number) && other.include?(number) }
end
def |(other)
Filter.new { |number| include?(number) || other.include?(number) }
end
end
class TypeFilter < Filter
def initialize(type)
case type
when :integer
super() { |number| number.class.superclass == Integer }
when :real
super() { |number| [Float, Rational].include? number.class }
when :complex
super() { |number| number.class == Complex }
end
end
end
class SignFilter < Filter
def initialize(option)
case option
when :positive then super() { |number| number > 0 }
when :non_positive then super() { |number| number <= 0 }
when :negative then super() { |number| number < 0 }
when :non_negative then super() { |number| number >= 0 }
end
end
end

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

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

Finished in 0.0228 seconds
24 examples, 0 failures

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

Мая обнови решението на 26.10.2014 21:46 (преди над 9 години)

+class NumberSet
+ include Enumerable
+
+ def initialize(new_set = [])
+ @internal_set = new_set.uniq
+ end
+
+ def <<(element)
+ @internal_set << element unless @internal_set.include? element
+ end
+
+ def each
+ @internal_set.each { |element| yield element }
+ end
+
+ def size
+ @internal_set.size
+ end
+
+ def empty?
+ @internal_set.size == 0
+ end
+
+ def [](filter)
+ NumberSet.new @internal_set.select { |element| filter[element] }
+ end
+end
+
+class Filter
+ def initialize(&block)
+ @block = block
+ end
+
+ def [](element)
+ @block.call element
+ end
+
+ def &(other)
+ Filter.new { |element| self[element] && other[element] }
+ end
+
+ def |(other)
+ Filter.new { |element| self[element] || other[element] }
+ end
+end
+
+class TypeFilter < Filter
+ def initialize(option)
+ @block = case option
+ when :integer then ->element { element.class.superclass == Integer }
+ when :real then ->element { [Float, Rational].include? element.class }
+ when :complex then ->element { element.class == Complex }
+ end
+ end
+end
+
+class SignFilter < Filter
+ def initialize(option)
+ @block = case option
+ when :positive then ->element { element > 0 }
+ when :non_positive then ->element { element <= 0 }
+ when :negative then ->element { element < 0 }
+ when :non_negative then ->element { element >= 0 }
+ end
+ end
+end

Мая обнови решението на 26.10.2014 21:48 (преди над 9 години)

class NumberSet
include Enumerable
def initialize(new_set = [])
@internal_set = new_set.uniq
end
def <<(element)
@internal_set << element unless @internal_set.include? element
end
def each
@internal_set.each { |element| yield element }
end
def size
@internal_set.size
end
def empty?
@internal_set.size == 0
end
def [](filter)
NumberSet.new @internal_set.select { |element| filter[element] }
end
end
class Filter
def initialize(&block)
@block = block
end
- def [](element)
- @block.call element
- end
+ def [](element)
+ @block.call element
+ end
def &(other)
- Filter.new { |element| self[element] && other[element] }
+ Filter.new { |element| self[element] && other[element] }
end
def |(other)
- Filter.new { |element| self[element] || other[element] }
+ Filter.new { |element| self[element] || other[element] }
end
end
class TypeFilter < Filter
def initialize(option)
@block = case option
- when :integer then ->element { element.class.superclass == Integer }
- when :real then ->element { [Float, Rational].include? element.class }
+ when :integer then ->element { element.class.superclass == Integer }
+ when :real then ->element { [Float, Rational].include? element.class }
when :complex then ->element { element.class == Complex }
- end
+ end
end
end
class SignFilter < Filter
def initialize(option)
@block = case option
when :positive then ->element { element > 0 }
when :non_positive then ->element { element <= 0 }
when :negative then ->element { element < 0 }
when :non_negative then ->element { element >= 0 }
end
end
end

Здрасти,

Ето няколко неща, върху които да помислиш:

  • NumberSet#each без подаден блок трябва да се държи като Array#each. При теб не е точно така.
  • Защо методът Filter#[] се казва така? Можеш ли да подбереш по-добро такова, така че да изразиш какво точно прави метода и какъв резултат връща.
  • Вместо да присвояваш lambda на @block във филтрите, можеш да извикаш конструктора на Filter с блок използвайки super() { |number| ... }.
  • Името @internal_set не ми говори какво точно държи обекта. Можеш ли да се възползваш от контекста на проблема и да подбереш по-добро име?

Мая обнови решението на 27.10.2014 01:30 (преди над 9 години)

class NumberSet
include Enumerable
def initialize(new_set = [])
- @internal_set = new_set.uniq
+ @number_set = new_set.uniq
end
- def <<(element)
- @internal_set << element unless @internal_set.include? element
+ def <<(number)
+ @number_set << number unless @number_set.include? number
end
def each
- @internal_set.each { |element| yield element }
+ return to_enum unless block_given?
+ @number_set.each { |number| yield number }
end
def size
- @internal_set.size
+ @number_set.size
end
def empty?
- @internal_set.size == 0
+ @number_set.size == 0
end
def [](filter)
- NumberSet.new @internal_set.select { |element| filter[element] }
+ NumberSet.new @number_set.select { |number| filter.include?(number) }
end
end
class Filter
def initialize(&block)
@block = block
end
- def [](element)
- @block.call element
+ def include?(number)
+ @block.call number
end
def &(other)
- Filter.new { |element| self[element] && other[element] }
+ Filter.new { |number| self.include?(number) && other.include?(number) }
end
def |(other)
- Filter.new { |element| self[element] || other[element] }
+ Filter.new { |number| self.include?(number) || other.include?(number) }
end
end
class TypeFilter < Filter
def initialize(option)
- @block = case option
- when :integer then ->element { element.class.superclass == Integer }
- when :real then ->element { [Float, Rational].include? element.class }
- when :complex then ->element { element.class == Complex }
+ case option
+ when :integer
+ super() { |number| number.class.superclass == Integer }
+ when :real
+ super() { |number| [Float, Rational].include? number.class }
+ when :complex
+ super() { |number| number.class == Complex }
end
end
end
class SignFilter < Filter
def initialize(option)
- @block = case option
- when :positive then ->element { element > 0 }
- when :non_positive then ->element { element <= 0 }
- when :negative then ->element { element < 0 }
- when :non_negative then ->element { element >= 0 }
+ case option
+ when :positive then super() { |number| number > 0 }
+ when :non_positive then super() { |number| number <= 0 }
+ when :negative then super() { |number| number < 0 }
+ when :non_negative then super() { |number| number >= 0 }
end
end
end

Мая обнови решението на 27.10.2014 01:32 (преди над 9 години)

class NumberSet
include Enumerable
def initialize(new_set = [])
@number_set = new_set.uniq
end
def <<(number)
@number_set << number unless @number_set.include? number
end
def each
return to_enum unless block_given?
@number_set.each { |number| yield number }
end
def size
@number_set.size
end
def empty?
@number_set.size == 0
end
def [](filter)
NumberSet.new @number_set.select { |number| filter.include?(number) }
end
end
class Filter
def initialize(&block)
@block = block
end
def include?(number)
@block.call number
end
def &(other)
Filter.new { |number| self.include?(number) && other.include?(number) }
end
def |(other)
Filter.new { |number| self.include?(number) || other.include?(number) }
end
end
class TypeFilter < Filter
def initialize(option)
case option
when :integer
- super() { |number| number.class.superclass == Integer }
+ super() { |number| number.class.superclass == Integer }
when :real
- super() { |number| [Float, Rational].include? number.class }
+ super() { |number| [Float, Rational].include? number.class }
when :complex
- super() { |number| number.class == Complex }
+ super() { |number| number.class == Complex }
end
end
end
class SignFilter < Filter
def initialize(option)
case option
when :positive then super() { |number| number > 0 }
when :non_positive then super() { |number| number <= 0 }
when :negative then super() { |number| number < 0 }
when :non_negative then super() { |number| number >= 0 }
end
end
end

Мерси за коментара, въпреки че съм от позакъснелите...

    • Консултирах се с документацията. Видях, че при липса на блок, трябва да не гърми, както беше в моя случай, а да връща Enumerator. Надявам се така да е коректно.
    • Преименувах го на include?, но не съм сигурна, че е добре. Не можах да измисля точно и кратко име за 'предикатът на филтъра е удовлетворен от'. (:
    • Благодаря за съвета с извикване на конструктора на базовия клас! В интерес на истината направих Filter базов, забелязвайки, че ще ми спести повторение на код, малко преди да предам решение.
    • Явно не ме бива с имената. Надявам се да е по-добре така.

    В заключение, съжалявам, че качвам всяка промяна по два пъти заради неуредици с идентацията. Не разбирам защо се получава така, уж съм се уверила, че е коректна и изцяло със space-ове, но при качване, нещата ми се поразместват. Може би sublime лъже. (:

    • Дори и да е коректно, защо е нужно да преоткриваш колелото? Много по-лесно би било да вземеш блока в NumberSet#each по име и после да го предадеш на Array#each директно. Същото важи и за empty?.
    • Що се отнася до имената - опитай се да направиш изречение и виж какво звучи добре. Множествата от числа съдържат в себе си множество от числа vs Множествата от числа съдържат в себе си числа. Типовите филтри филтрират по опция vs Типовите филтри филтрират по тип. Също почти никога не е ok да назовеш нещо, според това какво е в езика, а не какъв е смисълът му за дадения проблем (например блокове - block, масив - array, т.н.).
    • В Ruby e желателно да изпускаш self където е възможно.

    Мая обнови решението на 27.10.2014 10:50 (преди над 9 години)

    class NumberSet
    include Enumerable
    def initialize(new_set = [])
    - @number_set = new_set.uniq
    + @numbers = new_set.uniq
    end
    def <<(number)
    - @number_set << number unless @number_set.include? number
    + @numbers << number unless @numbers.include? number
    end
    - def each
    - return to_enum unless block_given?
    - @number_set.each { |number| yield number }
    + def each(&block)
    + @numbers.each &block
    end
    def size
    - @number_set.size
    + @numbers.size
    end
    def empty?
    - @number_set.size == 0
    + @numbers.empty?
    end
    def [](filter)
    - NumberSet.new @number_set.select { |number| filter.include?(number) }
    + NumberSet.new @numbers.select { |number| filter.include?(number) }
    end
    end
    class Filter
    def initialize(&block)
    @block = block
    end
    def include?(number)
    @block.call number
    end
    def &(other)
    - Filter.new { |number| self.include?(number) && other.include?(number) }
    + Filter.new { |number| include?(number) && other.include?(number) }
    end
    def |(other)
    - Filter.new { |number| self.include?(number) || other.include?(number) }
    + Filter.new { |number| include?(number) || other.include?(number) }
    end
    end
    class TypeFilter < Filter
    - def initialize(option)
    - case option
    + def initialize(type)
    + case type
    when :integer
    super() { |number| number.class.superclass == Integer }
    when :real
    super() { |number| [Float, Rational].include? number.class }
    when :complex
    super() { |number| number.class == Complex }
    end
    end
    end
    class SignFilter < Filter
    def initialize(option)
    case option
    when :positive then super() { |number| number > 0 }
    when :non_positive then super() { |number| number <= 0 }
    when :negative then super() { |number| number < 0 }
    when :non_negative then super() { |number| number >= 0 }
    end
    end
    end

    Мая обнови решението на 27.10.2014 11:13 (преди над 9 години)

    class NumberSet
    include Enumerable
    - def initialize(new_set = [])
    - @numbers = new_set.uniq
    + def initialize(numbers = [])
    + @numbers = numbers.uniq
    end
    def <<(number)
    @numbers << number unless @numbers.include? number
    end
    def each(&block)
    @numbers.each &block
    end
    def size
    @numbers.size
    end
    def empty?
    @numbers.empty?
    end
    def [](filter)
    NumberSet.new @numbers.select { |number| filter.include?(number) }
    end
    end
    class Filter
    def initialize(&block)
    @block = block
    end
    def include?(number)
    @block.call number
    end
    def &(other)
    Filter.new { |number| include?(number) && other.include?(number) }
    end
    def |(other)
    Filter.new { |number| include?(number) || other.include?(number) }
    end
    end
    class TypeFilter < Filter
    def initialize(type)
    case type
    when :integer
    super() { |number| number.class.superclass == Integer }
    when :real
    super() { |number| [Float, Rational].include? number.class }
    when :complex
    super() { |number| number.class == Complex }
    end
    end
    end
    class SignFilter < Filter
    def initialize(option)
    case option
    when :positive then super() { |number| number > 0 }
    when :non_positive then super() { |number| number <= 0 }
    when :negative then super() { |number| number < 0 }
    when :non_negative then super() { |number| number >= 0 }
    end
    end
    end

    Мая обнови решението на 27.10.2014 11:26 (преди над 9 години)

    class NumberSet
    include Enumerable
    def initialize(numbers = [])
    @numbers = numbers.uniq
    end
    def <<(number)
    @numbers << number unless @numbers.include? number
    end
    - def each(&block)
    - @numbers.each &block
    + def each(&operation)
    + @numbers.each &operation
    end
    def size
    @numbers.size
    end
    def empty?
    @numbers.empty?
    end
    def [](filter)
    NumberSet.new @numbers.select { |number| filter.include?(number) }
    end
    end
    class Filter
    - def initialize(&block)
    - @block = block
    + def initialize(&criterion)
    + @criterion = criterion
    end
    def include?(number)
    - @block.call number
    + @criterion.call number
    end
    def &(other)
    Filter.new { |number| include?(number) && other.include?(number) }
    end
    def |(other)
    Filter.new { |number| include?(number) || other.include?(number) }
    end
    end
    class TypeFilter < Filter
    def initialize(type)
    case type
    when :integer
    super() { |number| number.class.superclass == Integer }
    when :real
    super() { |number| [Float, Rational].include? number.class }
    when :complex
    super() { |number| number.class == Complex }
    end
    end
    end
    class SignFilter < Filter
    def initialize(option)
    case option
    when :positive then super() { |number| number > 0 }
    when :non_positive then super() { |number| number <= 0 }
    when :negative then super() { |number| number < 0 }
    when :non_negative then super() { |number| number >= 0 }
    end
    end
    end