Решение на Втора задача от Георги Георгиев

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

Към профила на Георги Георгиев

Резултати

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

Код

class Collection
include Enumerable
attr_accessor :songs
def initialize(songs = [])
@songs = songs
end
def self.parse(text)
text.split("\n\n").inject(Collection.new) do |collection, song|
name, artist, album = song.split("\n")
collection.songs << Song.new(name, artist, album)
collection
end
end
def names
songs.map { |song| song.name }.uniq
end
def artists
songs.map { |song| song.artist }.uniq
end
def albums
songs.map { |song| song.album }.uniq
end
def filter(criteria)
collection = songs.select { |song| criteria.match?(song) }
Collection.new(collection)
end
def adjoin(collection)
Collection.new(songs.concat(collection.songs).uniq)
end
def each
songs.each { |song| yield song }
end
end
class SubCriteria
attr_accessor :name, :artist, :album
def initialize
@name = { valid: [], invalid: [] }
@artist = { valid: [], invalid: [] }
@album = { valid: [], invalid: [] }
end
def &(other)
name.merge!(other.name) { |key, oldval, newval| oldval | newval }
artist.merge!(other.artist) { |key, oldval, newval| oldval | newval }
album.merge!(other.album) { |key, oldval, newval| oldval | newval }
self
end
def !
name[:valid], name[:invalid] = name[:invalid], name[:valid]
artist[:valid], artist[:invalid] = artist[:invalid], artist[:valid]
album[:valid], album[:invalid] = album[:invalid], album[:valid]
self
end
def name_match?(song)
valid = name[:valid]
invalid = name[:invalid]
return false if invalid.include?(song.name) || valid.length > 1
valid.empty? || valid.include?(song.name)
end
def artist_match?(song)
valid = artist[:valid]
invalid = artist[:invalid]
return false if invalid.include?(song.artist) || valid.length > 1
valid.empty? || valid.include?(song.artist)
end
def album_match?(song)
valid = album[:valid]
invalid = album[:invalid]
return false if invalid.include?(song.album) || valid.length > 1
valid.empty? || valid.include?(song.album)
end
end
class Criteria
attr_accessor :list
def initialize(list = [])
@list = list
end
def &(other)
criteria = list.product(other.list).map do |criteria|
criteria.inject(SubCriteria.new, :&)
end
Criteria.new(criteria)
end
def |(other)
criteria = list + other.list
Criteria.new(criteria)
end
def !
sub_criteria = list.inject(SubCriteria.new, :&)
Criteria.new([!sub_criteria])
end
def self.name(text)
sub_criteria = SubCriteria.new
sub_criteria.name[:valid] << text
Criteria.new([sub_criteria])
end
def self.artist(text)
sub_criteria = SubCriteria.new
sub_criteria.artist[:valid] << text
Criteria.new([sub_criteria])
end
def self.album(text)
sub_criteria = SubCriteria.new
sub_criteria.album[:valid] << text
Criteria.new([sub_criteria])
end
def match?(song)
list.any? do |sub_criteria|
sub_criteria.name_match?(song) &&
sub_criteria.artist_match?(song) &&
sub_criteria.album_match?(song)
end
end
end
class Song
attr_accessor :name, :artist, :album
def initialize(name, artist, album)
@name, @artist, @album = name, artist, album
end
end

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

...........

Finished in 0.01066 seconds
11 examples, 0 failures

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

Георги обнови решението на 30.10.2012 00:12 (преди над 11 години)

+
+class Collection
+ include Enumerable
+
+ attr_accessor :songs
+
+ def initialize(songs = [])
+ @songs = songs
+ end
+
+ def self.parse(text)
+ text.split("\n\n").inject(Collection.new) do |collection, song|
+ name, artist, album = song.split("\n")
+ collection.songs << Song.new(name, artist, album)
+ collection
+ end
+ end
+
+ def names
+ songs.map { |song| song.name }.uniq
+ end
+
+ def artists
+ songs.map { |song| song.artist }.uniq
+ end
+
+ def albums
+ songs.map { |song| song.album }.uniq
+ end
+
+ def filter(criteria)
+ collection = songs.select { |song| song.match?(criteria) }
+ Collection.new(collection)
+ end
+
+ def adjoin(collection)
+ Collection.new(songs.concat(collection.songs).uniq)
+ end
+
+ def each
+ songs.each { |song| yield song }
+ end
+end
+
+class Criterion
+ attr_accessor :name, :artist, :album
+
+ def initialize
+ @name = { valid: [], invalid: [] }
+ @artist = { valid: [], invalid: [] }
+ @album = { valid: [], invalid: [] }
+ end
+
+ def &(other)
+ name.merge!(other.name) { |key, oldval, newval| oldval | newval }
+ artist.merge!(other.artist) { |key, oldval, newval| oldval | newval }
+ album.merge!(other.album) { |key, oldval, newval| oldval | newval }
+ self
+ end
+
+ def !
+ name[:valid], name[:invalid] = name[:invalid], name[:valid]
+ artist[:valid], artist[:invalid] = artist[:invalid], artist[:valid]
+ album[:valid], album[:invalid] = album[:invalid], album[:valid]
+ self
+ end
+end
+
+class Criteria
+ attr_accessor :list
+
+ def initialize(list = [])
+ @list = list
+ end
+
+ def &(other)
+ criteria = list.product(other.list).map do |criteria|
+ criteria.inject(Criterion.new, :&)
+ end
+ Criteria.new(criteria)
+ end
+
+ def |(other)
+ criteria = list + other.list
+ Criteria.new(criteria)
+ end
+
+ def !
+ criterion = list.inject(Criterion.new, :&)
+ Criteria.new([!criterion])
+ end
+
+ def self.name(text)
+ criterion = Criterion.new
+ criterion.name[:valid] << text
+ Criteria.new([criterion])
+ end
+
+ def self.artist(text)
+ criterion = Criterion.new
+ criterion.artist[:valid] << text
+ Criteria.new([criterion])
+ end
+
+ def self.album(text)
+ criterion = Criterion.new
+ criterion.album[:valid] << text
+ Criteria.new([criterion])
+ end
+end
+
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(name, artist, album)
+ @name, @artist, @album = name, artist, album
+ end
+
+ def match?(criteria)
+ criteria.list.any? do |criteria|
+ name_match?(criteria) && artist_match?(criteria) && album_match?(criteria)
+ end
+ end
+
+ def name_match?(criterion)
+ valid = criterion.name[:valid]
+ invalid = criterion.name[:invalid]
+ return false if invalid.include?(name) || valid.length > 1
+ valid.empty? || valid.include?(name)
+ end
+
+ def artist_match?(criterion)
+ valid = criterion.artist[:valid]
+ invalid = criterion.artist[:invalid]
+ return false if invalid.include?(artist) || valid.length > 1
+ valid.empty? || valid.include?(artist)
+ end
+
+ def album_match?(criterion)
+ valid = criterion.album[:valid]
+ invalid = criterion.album[:invalid]
+ return false if invalid.include?(album) || valid.length > 1
+ valid.empty? || valid.include?(album)
+ end
+end

Георги обнови решението на 30.10.2012 08:44 (преди над 11 години)

-
class Collection
include Enumerable
attr_accessor :songs
def initialize(songs = [])
@songs = songs
end
def self.parse(text)
text.split("\n\n").inject(Collection.new) do |collection, song|
name, artist, album = song.split("\n")
collection.songs << Song.new(name, artist, album)
collection
end
end
def names
songs.map { |song| song.name }.uniq
end
def artists
songs.map { |song| song.artist }.uniq
end
def albums
songs.map { |song| song.album }.uniq
end
def filter(criteria)
collection = songs.select { |song| song.match?(criteria) }
Collection.new(collection)
end
def adjoin(collection)
Collection.new(songs.concat(collection.songs).uniq)
end
def each
songs.each { |song| yield song }
end
end
class Criterion
attr_accessor :name, :artist, :album
def initialize
@name = { valid: [], invalid: [] }
@artist = { valid: [], invalid: [] }
@album = { valid: [], invalid: [] }
end
def &(other)
name.merge!(other.name) { |key, oldval, newval| oldval | newval }
artist.merge!(other.artist) { |key, oldval, newval| oldval | newval }
album.merge!(other.album) { |key, oldval, newval| oldval | newval }
self
end
def !
name[:valid], name[:invalid] = name[:invalid], name[:valid]
artist[:valid], artist[:invalid] = artist[:invalid], artist[:valid]
album[:valid], album[:invalid] = album[:invalid], album[:valid]
self
end
end
class Criteria
attr_accessor :list
def initialize(list = [])
@list = list
end
def &(other)
criteria = list.product(other.list).map do |criteria|
criteria.inject(Criterion.new, :&)
end
Criteria.new(criteria)
end
def |(other)
criteria = list + other.list
Criteria.new(criteria)
end
def !
criterion = list.inject(Criterion.new, :&)
Criteria.new([!criterion])
end
def self.name(text)
criterion = Criterion.new
criterion.name[:valid] << text
Criteria.new([criterion])
end
def self.artist(text)
criterion = Criterion.new
criterion.artist[:valid] << text
Criteria.new([criterion])
end
def self.album(text)
criterion = Criterion.new
criterion.album[:valid] << text
Criteria.new([criterion])
end
end
class Song
attr_accessor :name, :artist, :album
def initialize(name, artist, album)
@name, @artist, @album = name, artist, album
end
def match?(criteria)
criteria.list.any? do |criteria|
name_match?(criteria) && artist_match?(criteria) && album_match?(criteria)
end
end
def name_match?(criterion)
valid = criterion.name[:valid]
invalid = criterion.name[:invalid]
return false if invalid.include?(name) || valid.length > 1
valid.empty? || valid.include?(name)
end
def artist_match?(criterion)
valid = criterion.artist[:valid]
invalid = criterion.artist[:invalid]
return false if invalid.include?(artist) || valid.length > 1
valid.empty? || valid.include?(artist)
end
def album_match?(criterion)
valid = criterion.album[:valid]
invalid = criterion.album[:invalid]
return false if invalid.include?(album) || valid.length > 1
valid.empty? || valid.include?(album)
end
end

Дизайна ти е объркан.

Методите за проверка дали песен отговаря на някакво условие са в песента. Criteria класът ти е труден за рабзиране. Имаш много повторение на код между различните методи. Наличието на два класа, Criteria и Criterion е объркващо.

Най-голямата ти концептуална грешка идва от имплементацията на Collection#filter. Ако го напишеш като @songs.select { |song| criteria.match?(song) }, ще откриеш, че това ще те доведе до доста по-чист дизайн.

Георги обнови решението на 31.10.2012 13:48 (преди над 11 години)

class Collection
include Enumerable
attr_accessor :songs
def initialize(songs = [])
@songs = songs
end
def self.parse(text)
text.split("\n\n").inject(Collection.new) do |collection, song|
name, artist, album = song.split("\n")
collection.songs << Song.new(name, artist, album)
collection
end
end
def names
songs.map { |song| song.name }.uniq
end
def artists
songs.map { |song| song.artist }.uniq
end
def albums
songs.map { |song| song.album }.uniq
end
def filter(criteria)
- collection = songs.select { |song| song.match?(criteria) }
+ collection = songs.select { |song| criteria.match?(song) }
Collection.new(collection)
end
def adjoin(collection)
Collection.new(songs.concat(collection.songs).uniq)
end
def each
songs.each { |song| yield song }
end
end
-class Criterion
+class SubCriteria
attr_accessor :name, :artist, :album
def initialize
@name = { valid: [], invalid: [] }
@artist = { valid: [], invalid: [] }
@album = { valid: [], invalid: [] }
end
def &(other)
name.merge!(other.name) { |key, oldval, newval| oldval | newval }
artist.merge!(other.artist) { |key, oldval, newval| oldval | newval }
album.merge!(other.album) { |key, oldval, newval| oldval | newval }
self
end
def !
name[:valid], name[:invalid] = name[:invalid], name[:valid]
artist[:valid], artist[:invalid] = artist[:invalid], artist[:valid]
album[:valid], album[:invalid] = album[:invalid], album[:valid]
self
end
+
+ def name_match?(song)
+ valid = name[:valid]
+ invalid = name[:invalid]
+ return false if invalid.include?(song.name) || valid.length > 1
+ valid.empty? || valid.include?(song.name)
+ end
+
+ def artist_match?(song)
+ valid = artist[:valid]
+ invalid = artist[:invalid]
+ return false if invalid.include?(song.artist) || valid.length > 1
+ valid.empty? || valid.include?(song.artist)
+ end
+
+ def album_match?(song)
+ valid = album[:valid]
+ invalid = album[:invalid]
+ return false if invalid.include?(song.album) || valid.length > 1
+ valid.empty? || valid.include?(song.album)
+ end
end
class Criteria
attr_accessor :list
def initialize(list = [])
@list = list
end
def &(other)
criteria = list.product(other.list).map do |criteria|
- criteria.inject(Criterion.new, :&)
+ criteria.inject(SubCriteria.new, :&)
end
Criteria.new(criteria)
end
def |(other)
criteria = list + other.list
Criteria.new(criteria)
end
def !
- criterion = list.inject(Criterion.new, :&)
- Criteria.new([!criterion])
+ sub_criteria = list.inject(SubCriteria.new, :&)
+ Criteria.new([!sub_criteria])
end
def self.name(text)
- criterion = Criterion.new
- criterion.name[:valid] << text
- Criteria.new([criterion])
+ sub_criteria = SubCriteria.new
+ sub_criteria.name[:valid] << text
+ Criteria.new([sub_criteria])
end
def self.artist(text)
- criterion = Criterion.new
- criterion.artist[:valid] << text
- Criteria.new([criterion])
+ sub_criteria = SubCriteria.new
+ sub_criteria.artist[:valid] << text
+ Criteria.new([sub_criteria])
end
def self.album(text)
- criterion = Criterion.new
- criterion.album[:valid] << text
- Criteria.new([criterion])
+ sub_criteria = SubCriteria.new
+ sub_criteria.album[:valid] << text
+ Criteria.new([sub_criteria])
end
+ def match?(song)
+ list.any? do |sub_criteria|
+ sub_criteria.name_match?(song) &&
+ sub_criteria.artist_match?(song) &&
+ sub_criteria.album_match?(song)
+ end
+ end
end
class Song
attr_accessor :name, :artist, :album
def initialize(name, artist, album)
@name, @artist, @album = name, artist, album
- end
-
- def match?(criteria)
- criteria.list.any? do |criteria|
- name_match?(criteria) && artist_match?(criteria) && album_match?(criteria)
- end
- end
-
- def name_match?(criterion)
- valid = criterion.name[:valid]
- invalid = criterion.name[:invalid]
- return false if invalid.include?(name) || valid.length > 1
- valid.empty? || valid.include?(name)
- end
-
- def artist_match?(criterion)
- valid = criterion.artist[:valid]
- invalid = criterion.artist[:invalid]
- return false if invalid.include?(artist) || valid.length > 1
- valid.empty? || valid.include?(artist)
- end
-
- def album_match?(criterion)
- valid = criterion.album[:valid]
- invalid = criterion.album[:invalid]
- return false if invalid.include?(album) || valid.length > 1
- valid.empty? || valid.include?(album)
end
end

Георги обнови решението на 31.10.2012 13:51 (преди над 11 години)

class Collection
include Enumerable
attr_accessor :songs
def initialize(songs = [])
@songs = songs
end
def self.parse(text)
text.split("\n\n").inject(Collection.new) do |collection, song|
name, artist, album = song.split("\n")
collection.songs << Song.new(name, artist, album)
collection
end
end
def names
songs.map { |song| song.name }.uniq
end
def artists
songs.map { |song| song.artist }.uniq
end
def albums
songs.map { |song| song.album }.uniq
end
def filter(criteria)
collection = songs.select { |song| criteria.match?(song) }
Collection.new(collection)
end
def adjoin(collection)
Collection.new(songs.concat(collection.songs).uniq)
end
def each
songs.each { |song| yield song }
end
end
class SubCriteria
attr_accessor :name, :artist, :album
def initialize
@name = { valid: [], invalid: [] }
@artist = { valid: [], invalid: [] }
@album = { valid: [], invalid: [] }
end
def &(other)
name.merge!(other.name) { |key, oldval, newval| oldval | newval }
artist.merge!(other.artist) { |key, oldval, newval| oldval | newval }
album.merge!(other.album) { |key, oldval, newval| oldval | newval }
self
end
def !
name[:valid], name[:invalid] = name[:invalid], name[:valid]
artist[:valid], artist[:invalid] = artist[:invalid], artist[:valid]
album[:valid], album[:invalid] = album[:invalid], album[:valid]
self
end
def name_match?(song)
valid = name[:valid]
invalid = name[:invalid]
return false if invalid.include?(song.name) || valid.length > 1
valid.empty? || valid.include?(song.name)
end
def artist_match?(song)
valid = artist[:valid]
invalid = artist[:invalid]
return false if invalid.include?(song.artist) || valid.length > 1
valid.empty? || valid.include?(song.artist)
end
def album_match?(song)
valid = album[:valid]
invalid = album[:invalid]
return false if invalid.include?(song.album) || valid.length > 1
valid.empty? || valid.include?(song.album)
end
end
class Criteria
attr_accessor :list
def initialize(list = [])
@list = list
end
def &(other)
criteria = list.product(other.list).map do |criteria|
criteria.inject(SubCriteria.new, :&)
end
Criteria.new(criteria)
end
def |(other)
criteria = list + other.list
Criteria.new(criteria)
end
def !
sub_criteria = list.inject(SubCriteria.new, :&)
Criteria.new([!sub_criteria])
end
def self.name(text)
sub_criteria = SubCriteria.new
sub_criteria.name[:valid] << text
Criteria.new([sub_criteria])
end
def self.artist(text)
sub_criteria = SubCriteria.new
sub_criteria.artist[:valid] << text
Criteria.new([sub_criteria])
end
def self.album(text)
sub_criteria = SubCriteria.new
sub_criteria.album[:valid] << text
Criteria.new([sub_criteria])
end
+
def match?(song)
list.any? do |sub_criteria|
sub_criteria.name_match?(song) &&
sub_criteria.artist_match?(song) &&
sub_criteria.album_match?(song)
end
end
end
class Song
attr_accessor :name, :artist, :album
def initialize(name, artist, album)
@name, @artist, @album = name, artist, album
end
end