Решение на Втора задача от Петко Борджуков

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

Към профила на Петко Борджуков

Резултати

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

Код

require 'enumerator'
require 'forwardable'
class Collection
include Enumerable
extend Forwardable
attr_accessor :songs
def self.parse(text)
new text.split("\n\n").map { |block| Song.parse block }
end
def initialize(songs)
@songs = songs
end
def filter(criteria)
Collection.new @songs.select { |song| song.matches? criteria }
end
def artists
@songs.map { |song| song.artist }.uniq
end
def names
@songs.map { |song| song.name }.uniq
end
def albums
@songs.map { |song| song.album }.uniq
end
def adjoin(collection)
Collection.new(songs | collection.songs)
end
def_delegator :@songs, :each
end
module Criteria
def self.name(name)
InclusiveCriterion.new name: name
end
def self.artist(artist)
InclusiveCriterion.new artist: artist
end
def self.album(album)
InclusiveCriterion.new album: album
end
class Criterion
def initialize(criteria)
@criteria = criteria
end
def &(criterion)
CriteriaConjunction.new [self, criterion]
end
def |(criterion)
CriteriaDisjunction.new [self, criterion]
end
end
class CriteriaConjunction < Criterion
def fulfilled_for?(song)
@criteria.all? { |criterion| criterion.fulfilled_for? song }
end
def !()
CriteriaDisjunction.new @criteria.map { |criterion| !criterion }
end
end
class CriteriaDisjunction < Criterion
def !()
CriteriaConjunction.new @criteria.map { |criterion| !criterion }
end
def fulfilled_for?(song)
@criteria.any? { |criterion| criterion.fulfilled_for? song }
end
end
class ExclusiveCriterion < Criterion
def fulfilled_for?(song)
@criteria.none? { |tag, value| value == song.tags[tag] }
end
def !()
InclusiveCriterion.new @criteria
end
end
class InclusiveCriterion < Criterion
def fulfilled_for?(song)
@criteria.all? { |tag, value| value == song.tags[tag] }
end
def !()
ExclusiveCriterion.new @criteria
end
end
end
class Song
attr_accessor :name, :artist, :album
def initialize(tags = {})
@name, @artist, @album = tags[:name], tags[:artist], tags[:album]
end
def tags()
{name: @name, artist: @artist, album: @album}
end
def matches?(criteria)
criteria.fulfilled_for? self
end
def self.parse(text)
new Hash[[:name, :artist, :album].zip text.split "\n"]
end
end

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

...........

Finished in 0.01032 seconds
11 examples, 0 failures

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

Петко обнови решението на 27.10.2012 17:32 (преди над 12 години)

+require 'enumerator'
+require 'forwardable'
+
+class Collection
+ include Enumerable
+ extend Forwardable
+
+ def self.parse(text)
+ new text.split("\n\n").map { |block| Song.new block }
+ end
+
+ def initialize(songs)
+ @songs = songs
+ end
+
+ def_delegator :@songs, :each
+end
+
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(block)
+ @name, @artist, @album = block.split "\n"
+ end
+end
+
+class Criteria
+ def initialize(tags, inclusive = true)
+ @tags, @inclusive = tags, inclusive
+ end
+
+ def self.name(name)
+ new name: name
+ end
+
+ def self.artist(artist)
+ new artist: artist
+ end
+
+ def self.album(album)
+ new album: album
+ end
+
+ def inclusive?
+ @inclusive
+ end
+
+ def !()
+ Criteria.new @tags, !@inclusive
+ end
+end

Единственото, което намирам за много крива идея, е да подаваш текстов блок на конструктора на Song. По-добре подай три позиционни аргумента и остави парсенето на някой друг.

Иначе - пушка.

Петко обнови решението на 30.10.2012 19:31 (преди над 12 години)

require 'enumerator'
require 'forwardable'
class Collection
include Enumerable
extend Forwardable
+ attr_accessor :songs
+
def self.parse(text)
- new text.split("\n\n").map { |block| Song.new block }
+ new text.split("\n\n").map { |block| Song.parse block }
end
def initialize(songs)
@songs = songs
end
- def_delegator :@songs, :each
-end
+ def filter(criteria)
+ Collection.new @songs.select { |song| song.matches? criteria }
+ end
-class Song
- attr_accessor :name, :artist, :album
+ def artists
+ @songs.map { |song| song.artist }.uniq
+ end
- def initialize(block)
- @name, @artist, @album = block.split "\n"
+ def names
+ @songs.map { |song| song.name }.uniq
end
-end
-class Criteria
- def initialize(tags, inclusive = true)
- @tags, @inclusive = tags, inclusive
+ def albums
+ @songs.map { |song| song.album }.uniq
end
+ def adjoin(collection)
+ Collection.new(songs | collection.songs)
+ end
+
+ def_delegator :@songs, :each
+end
+
+module Criteria
def self.name(name)
- new name: name
+ InclusiveCriterion.new name: name
end
def self.artist(artist)
- new artist: artist
+ InclusiveCriterion.new artist: artist
end
def self.album(album)
- new album: album
+ InclusiveCriterion.new album: album
end
- def inclusive?
- @inclusive
+ class Criterion
+ def initialize(criteria)
+ @criteria = criteria
+ end
+
+ def &(criterion)
+ CriteriaConjunction.new [self, criterion]
+ end
+
+ def |(criterion)
+ CriteriaDisjunction.new [self, criterion]
+ end
end
- def !()
- Criteria.new @tags, !@inclusive
+ class CriteriaConjunction < Criterion
+ def fulfilled_for?(song)
+ @criteria.all? { |criterion| criterion.fulfilled_for? song }
+ end
+
+ def !()
+ CriteriaDisjunction.new @criteria.map { |criterion| !criterion }
+ end
+ end
+
+ class CriteriaDisjunction < Criterion
+ def !()
+ CriteriaConjunction.new @criteria.map { |criterion| !criterion }
+ end
+
+ def fulfilled_for?(song)
+ @criteria.any? { |criterion| criterion.fulfilled_for? song }
+ end
+ end
+
+ class ExclusiveCriterion < Criterion
+ def fulfilled_for?(song)
+ @criteria.none? { |tag, value| value == song.tags[tag] }
+ end
+
+ def !()
+ InclusiveCriterion.new @criteria
+ end
+ end
+
+ class InclusiveCriterion < Criterion
+ def fulfilled_for?(song)
+ @criteria.all? { |tag, value| value == song.tags[tag] }
+ end
+
+ def !()
+ ExclusiveCriterion.new @criteria
+ end
+ end
+end
+
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(tags = {})
+ @name, @artist, @album = tags[:name], tags[:artist], tags[:album]
+ end
+
+ def tags()
+ {name: @name, artist: @artist, album: @album}
+ end
+
+ def matches?(criteria)
+ criteria.fulfilled_for? self
+ end
+
+ def self.parse(text)
+ new Hash[[:name, :artist, :album].zip text.split "\n"]
end
end