Камелия обнови решението на 30.10.2012 01:48 (преди около 12 години)
+class Collection
+ include Enumerable
+
+ attr_accessor :songs
+
+ def initialize(songs = [])
+ @songs = songs
+ end
+
+ def each
+ @songs.each { |song| yield song }
+ end
+
+ def self.parse(songs_string)
+ songs_list = songs_string.split("\n\n").map do |song_string|
+ Song.new(song_string.split("\n"))
+ end
+ Collection.new(songs_list)
+ end
+
+ def artists
+ map { |song| song.artist }.uniq
+ end
+
+ def albums
+ map { |song| song.album }.uniq
+ end
+
+ def names
+ map { |song| song.name }.uniq
+ end
+
+ def adjoin(other)
+ result = Collection.new
+ each { |song| result.songs << song }
+ other.each { |song| result.songs << song }
+ result
+ end
+
+ def filter(criteria)
+ Collection.new(select { |song| criteria.criteria.(song) })
+ end
+end
+
+class Song
+ attr_accessor :artist, :album, :name
+
+ def initialize(song_data)
+ @artist = song_data[1]
+ @album = song_data[2]
+ @name = song_data[0]
+ end
+end
+
+class Criteria
+ attr_accessor :criteria
+
+ def initialize(criteria)
+ @criteria = criteria
+ end
+
+ def self.artist(artist)
+ new lambda { |song| song.artist == artist }
+ end
+
+ def self.album(album)
+ new lambda { |song| song.album == album }
+ end
+
+ def self.name(name)
+ new lambda { |song| song.name == name }
+ end
+
+ def &(other)
+ Criteria.new lambda { |song| criteria.(song) and other.criteria.(song) }
+ end
+
+ def |(other)
+ Criteria.new lambda { |song| criteria.(song) or other.criteria.(song) }
+ end
+
+ def !
+ Criteria.new lambda { |song| not criteria.(song) }
+ end
+end