Любомир обнови решението на 31.10.2012 02:45 (преди около 12 години)
+class Collection
+ include Enumerable
+
+ def initialize collection
+ @collection = collection
+ end
+
+ def Collection.parse text
+ songs = []
+ text.split(/^[\s]*$\n/).each { |song| songs << Song.new(song) }
+ Collection.new songs
+ end
+
+ def each &block
+ @collection.each{ |member| block.call member }
+ end
+
+ def filter criteria
+ Collection.new select { |song| criteria.call song }
+ end
+
+ def adjoin collection
+ Collection.new zip(collection).flatten.compact
+ end
+
+ def names
+ @collection.map { |song| song.name }.uniq
+ end
+
+ def artists
+ @collection.map { |song| song.artist }.uniq
+ end
+
+ def albums
+ @collection.map { |song| song.album }.uniq
+ end
+end
+
+class Song
+ def initialize text
+ @song_data = text
+ end
+
+ def name
+ @song_data.split("\n")[0]
+ end
+
+ def artist
+ @song_data.split("\n")[1]
+ end
+
+ def album
+ @song_data.split("\n")[2]
+ end
+end
+
+class Criteria
+ def initialize criteria
+ @criteria = criteria
+ end
+
+ def & other
+ Criteria.new proc { |song| @criteria.call(song) and other.call(song) }
+ end
+
+ def | other
+ Criteria.new proc { |song| @criteria.call(song) or other.call(song) }
+ end
+
+ def !
+ Criteria.new proc { |song| not @criteria.call song }
+ end
+
+ def call song
+ @criteria.call song
+ end
+
+ def Criteria.name name
+ Criteria.new proc { |song| name == song.name }
+ end
+
+ def Criteria.artist artist
+ Criteria.new proc { |song| artist == song.artist }
+ end
+
+ def Criteria.album album
+ Criteria.new proc { |song| album == song.album }
+ end
+end