Георги обнови решението на 31.10.2012 12:54 (преди около 12 години)
+class Song
+ attr_reader :name, :artist, :album
+
+ def initialize(name, artist, album)
+ @name, @artist, @album = name, artist, album
+ end
+end
+
+class Criteria
+ attr_reader :criterias
+
+ def initialize(criterias)
+ @criterias = criterias
+ end
+
+ def self.name(value)
+ Criteria.new lambda{ |song| song.name == value }
+ end
+
+ def self.album(value)
+ Criteria.new lambda{ |song| song.album == value }
+ end
+
+ def self.artist(value)
+ Criteria.new lambda{ |song| song.artist == value }
+ end
+
+ def &(other)
+ new_criteria = lambda do |song|
+ criterias.call(song) && other.criterias.call(song)
+ end
+
+ Criteria.new new_criteria
+ end
+
+ def |(other)
+ new_criteria = lambda do |song|
+ criterias.call(song) || other.criterias.call(song)
+ end
+
+ Criteria.new new_criteria
+ end
+
+ def !
+ Criteria.new lambda { |song| !criterias.call(song) }
+ end
+end
+
+class Collection
+ include Enumerable
+
+ attr_reader :song_list
+
+ def initialize(song_list)
+ @song_list = song_list
+ end
+
+ def self.parse(input)
+ song_list = []
+
+ input.split("\n").delete_if(&:empty?).each_slice(3) do |song_value|
+ song_list << Song.new(*song_value)
+ end
+
+ Collection.new song_list
+ end
+
+ def each(&block)
+ @song_list.each(&block)
+ end
+
+ def artists
+ @song_list.map { |song| song.artist }.uniq
+ end
+
+ def names
+ @song_list.map { |song| song.name }.uniq
+ end
+
+ def albums
+ @song_list.map { |song| song.album }.uniq
+ end
+
+ def filter(criteria)
+ Collection.new select(&criteria.criterias)
+ end
+
+ def adjoin(other)
+ Collection.new song_list | other.song_list
+ end
+end