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

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

Към профила на Елена Миронова

Резултати

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

Код

module Music
class Collection
attr_reader :songs
def initialize(songs)
@songs = songs
end
include Enumerable
def each
@songs.each do |song|
yield song
end
end
def self.parse(text)
collection = Collection.new []
text.each_line.each_slice(4) do |slice|
collection.songs << Song.new(slice[0], slice[1], slice[2])
end
return collection
end
def artists
@songs.map(&:artist).uniq
end
def albums
@songs.map(&:album).uniq
end
def names
@songs.map(&:name).uniq
end
def filter(criteria)
s = []
#Collection.new(select { |song| s << song if song.satisfy?(criteria) })
end
def adjoin(collection_to_join)
union = Collection.new []
union.songs.concat(@songs).concat(collection_to_join.songs)
return union
end
end
class CriteriaPart
attr_reader :kind, :value
attr_accessor :operator, :self_operator
def initialize(kind, value)
@kind = kind
@value = value
end
end
class Criteria
attr_accessor :parts
def initialize(criteria_part)
@parts = []
@parts << criteria_part
end
def self.name(song_name)
Criteria.new(CriteriaPart.new('name', song_name))
end
def self.artist(song_artist)
Criteria.new(CriteriaPart.new('artist', song_artist))
end
def self.album(song_album)
Criteria.new(CriteriaPart.new('album', song_album))
end
def & other
@parts.last.operator = '&'
@parts.concat(other.parts)
return self
end
def | other
@parts.last.operator = '|'
@parts.concat(other.parts)
return self
end
def !
@parts.first.self_operator = '!='
return self
end
def next_part(criteria_part)
end
end
class Song
attr_accessor :name, :artist, :album
def initialize(name, artist, album)
@name = name
@artist = artist
@album = album
end
def satisfy?(criteria)
satisfy = satisfy_part?(criteria.parts.first)
criteria.parts.each_with_index do |part, index|
#satisfy = satisfy.send part.operator, satisfy_part?(criteria.parts[index+1])
end
return satisfy
end
def satisfy_part?(criteria_part)
if criteria_part.self_operator == '!='
return (send(criteria_part.kind)).gsub(/\n/,'') != criteria_part.value
else
return (send(criteria_part.kind)).gsub(/\n/,'') == criteria_part.value
end
end
end
end

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

FFFFFFFFFFF

Failures:

  1) Collection can find all the artists in the collection
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:5:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Collection can find all the names of all songs in the collection
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:17:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Collection can find all the albums in the collection
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:30:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Collection can be filtered by song name
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:44:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Collection can be filtered by song name
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:49:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Collection can be filtered by album
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:54:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Collection can return an empty result
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:59:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Collection supports a conjuction of filters
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:64:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) Collection supports a disjunction of filters
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:69:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  10) Collection supports negation of filters
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:78:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  11) Collection can be adjoined with another collection
     Failure/Error: let(:collection) { Collection.parse(SONGS) }
     NameError:
       uninitialized constant Collection
     # /tmp/d20130203-23049-3axfpv/spec.rb:2:in `block (2 levels) in <top (required)>'
     # /tmp/d20130203-23049-3axfpv/spec.rb:83:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.02164 seconds
11 examples, 11 failures

Failed examples:

rspec /tmp/d20130203-23049-3axfpv/spec.rb:4 # Collection can find all the artists in the collection
rspec /tmp/d20130203-23049-3axfpv/spec.rb:16 # Collection can find all the names of all songs in the collection
rspec /tmp/d20130203-23049-3axfpv/spec.rb:29 # Collection can find all the albums in the collection
rspec /tmp/d20130203-23049-3axfpv/spec.rb:43 # Collection can be filtered by song name
rspec /tmp/d20130203-23049-3axfpv/spec.rb:48 # Collection can be filtered by song name
rspec /tmp/d20130203-23049-3axfpv/spec.rb:53 # Collection can be filtered by album
rspec /tmp/d20130203-23049-3axfpv/spec.rb:58 # Collection can return an empty result
rspec /tmp/d20130203-23049-3axfpv/spec.rb:63 # Collection supports a conjuction of filters
rspec /tmp/d20130203-23049-3axfpv/spec.rb:68 # Collection supports a disjunction of filters
rspec /tmp/d20130203-23049-3axfpv/spec.rb:77 # Collection supports negation of filters
rspec /tmp/d20130203-23049-3axfpv/spec.rb:82 # Collection can be adjoined with another collection

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

Елена обнови решението на 29.10.2012 13:34 (преди около 12 години)

+module Music
+ class Collection
+ attr_reader :songs
+
+ def initialize
+ @songs = []
+ end
+
+ include Enumerable
+
+ def each
+ @songs.each do |song|
+ yield song
+ end
+ end
+
+ def self.parse (text)
+ collection = Collection.new
+ text.each_line.each_slice(4) do |slice|
+ collection.songs << Song.new(slice[0], slice[1], slice[2])
+ end
+ return collection
+ end
+
+ def artists
+ @songs.map(&:artist).uniq
+ end
+
+ def albums
+ @songs.map(&:album).uniq
+ end
+
+ def names
+ @songs.map(&:name).uniq
+ end
+
+ def filter criteria
+ #collection = Collection.new
+ #select do |song|
+ #collection.songs << song if song.send(criteria.kind) == criteria.value
+ #end
+ #return collection.filter(criteria.other) if criteria.op == '&'
+ #return collection.adjoin(self.filter(criteria.other)) if criteria.op == '|'
+ #return collection
+ end
+
+ def adjoin collection_to_join
+ union = Collection.new
+ union.songs.concat(@songs).concat(collection_to_join.songs)
+ return union
+ end
+ end
+
+ class Criteria
+ attr_accessor :kind, :value, :self_op, :other, :op
+
+ def initialize kind, value, other, op
+ @kind = kind
+ @value = value
+ #@self_op = '=='
+ @other = other
+ @op = op
+ end
+
+ def self.name song_name
+ Criteria.new 'name', song_name, nil, nil
+ end
+
+ def self.artist song_artist
+ Criteria.new 'artist', song_artist, nil, nil
+ end
+
+ def self.album song_album
+ Criteria.new 'album', song_album, nil, nil
+ end
+
+ def & (other)
+ Criteria.new @kind, @value, other, '&'
+ end
+
+ def | (other)
+ Criteria.new @kind, @value, other, '|'
+ end
+
+ def !
+ @self_op = '!='
+ end
+ end
+
+ class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize name, artist, album
+ @name = name
+ @artist = artist
+ @album = album
+ end
+ end
+end

Бих искала да попитам относно методите filter и adjoin:

Collection с "класов" метод parse и методи artists, albums, names, filter и adjoin. Последните два връщат нещо, което има същите методи.

Означава ли, че filter и adjoin могат да връщат масив от песни, и под "същите методи" кое се има предвид?

Тази имплементация на метода filter подходяща ли е?

Преди всичко, не спазваш конвенции. Идентацията ти е объркана. Погледни как излиза на сайта. Това е най-вероятно, защото редактора ти добавя Tab-ове (дори ти да не натискаш клавиша Tab докато пишеш).

Преди всичко 2, редактирал съм ти въпроса. Натисни редактирай и виж как съм го променил, за да изглежда така. Форумите имат функционалност за форматиране (Markdown), опитай да я научиш и да я ползваш. Стандартен формат.

Сега за въпроса ти. filter и adjoin връщат подмножество на колекция. "Същите методи" са artists, albums, names, filter и adjoin. Демек каквото можеш да направиш с Collection, трябва да можеш да направиш и с подмножество на колекция. Ако опира до имплементация, имаш няколко варианта. Можеш да върнеш колекция. Можеш да направиш клас за подмножество на колекция и да върнеш него. Може да измислиш нещо трето. От теб зависи.

Имплементация е ОК, но е лоша. Първо, няма да мине skeptic изискванията. Второ, вместо да конструираш колекция и да й мутираш песните, можеш просто да ги подаваш като аргумент на конструктора. Трето, вместо Collection#filter да знае как да интерпретира обект от тип Criteria, опитай да преместиш тази функционалност в Criteria. Така интерфейса ще е по-чист. И финално, опитай да направиш наследници на Criteria за всяка възможност или поне да ползваш ламбди, вместо много if-ове за различните видове критерии.

Елена обнови решението на 31.10.2012 16:59 (преди около 12 години)

module Music
class Collection
attr_reader :songs
- def initialize
- @songs = []
+ def initialize(songs)
+ @songs = songs
end
include Enumerable
def each
@songs.each do |song|
yield song
end
end
- def self.parse (text)
- collection = Collection.new
+ def self.parse(text)
+ collection = Collection.new []
text.each_line.each_slice(4) do |slice|
collection.songs << Song.new(slice[0], slice[1], slice[2])
end
return collection
end
def artists
@songs.map(&:artist).uniq
end
def albums
@songs.map(&:album).uniq
end
def names
@songs.map(&:name).uniq
end
- def filter criteria
- #collection = Collection.new
- #select do |song|
- #collection.songs << song if song.send(criteria.kind) == criteria.value
- #end
- #return collection.filter(criteria.other) if criteria.op == '&'
- #return collection.adjoin(self.filter(criteria.other)) if criteria.op == '|'
- #return collection
+ def filter(criteria)
+ s = []
+ #Collection.new(select { |song| s << song if song.satisfy?(criteria) })
end
- def adjoin collection_to_join
- union = Collection.new
- union.songs.concat(@songs).concat(collection_to_join.songs)
- return union
+ def adjoin(collection_to_join)
+ union = Collection.new []
+ union.songs.concat(@songs).concat(collection_to_join.songs)
+ return union
end
end
- class Criteria
- attr_accessor :kind, :value, :self_op, :other, :op
+ class CriteriaPart
+ attr_reader :kind, :value
+ attr_accessor :operator, :self_operator
- def initialize kind, value, other, op
- @kind = kind
+ def initialize(kind, value)
+ @kind = kind
@value = value
- #@self_op = '=='
- @other = other
- @op = op
- end
+ end
+ end
- def self.name song_name
- Criteria.new 'name', song_name, nil, nil
- end
+ class Criteria
+ attr_accessor :parts
- def self.artist song_artist
- Criteria.new 'artist', song_artist, nil, nil
- end
+ def initialize(criteria_part)
+ @parts = []
+ @parts << criteria_part
+ end
- def self.album song_album
- Criteria.new 'album', song_album, nil, nil
- end
+ def self.name(song_name)
+ Criteria.new(CriteriaPart.new('name', song_name))
+ end
- def & (other)
- Criteria.new @kind, @value, other, '&'
- end
+ def self.artist(song_artist)
+ Criteria.new(CriteriaPart.new('artist', song_artist))
+ end
- def | (other)
- Criteria.new @kind, @value, other, '|'
- end
+ def self.album(song_album)
+ Criteria.new(CriteriaPart.new('album', song_album))
+ end
- def !
- @self_op = '!='
+ def & other
+ @parts.last.operator = '&'
+ @parts.concat(other.parts)
+ return self
+ end
+
+ def | other
+ @parts.last.operator = '|'
+ @parts.concat(other.parts)
+ return self
+ end
+
+ def !
+ @parts.first.self_operator = '!='
+ return self
+ end
+
+ def next_part(criteria_part)
end
end
class Song
attr_accessor :name, :artist, :album
- def initialize name, artist, album
+ def initialize(name, artist, album)
@name = name
@artist = artist
@album = album
end
+
+ def satisfy?(criteria)
+ satisfy = satisfy_part?(criteria.parts.first)
+ criteria.parts.each_with_index do |part, index|
+ #satisfy = satisfy.send part.operator, satisfy_part?(criteria.parts[index+1])
+ end
+ return satisfy
+ end
+
+ def satisfy_part?(criteria_part)
+ if criteria_part.self_operator == '!='
+ return (send(criteria_part.kind)).gsub(/\n/,'') != criteria_part.value
+ else
+ return (send(criteria_part.kind)).gsub(/\n/,'') == criteria_part.value
+ end
+ end
end
-end
+end