Снежана обнови решението на 31.10.2012 14:03 (преди около 12 години)
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(text)
+ lines = text.split(/\r?\n/)
+ @name = lines[0]
+ @artist = lines[1]
+ @album = lines[2]
+ end
+end
+
+class Criteria
+ def call(song)
+ @criteria.call song
+ end
+
+ def initialize(criteria)
+ @criteria = criteria
+ end
+
+ def self.name(name)
+ Criteria.new lambda { |song| name == song.name }
+ end
+
+ def self.artist(artist)
+ Criteria.new lambda { |song| artist == song.artist }
+ end
+
+ def self.album(album)
+ Criteria.new lambda { |song| album == song.album }
+ end
+
+ def |(other)
+ Criteria.new lambda { |song| self.call(song) or other.call(song) }
+ end
+
+ def &(other)
+ Criteria.new lambda { |song| self.call(song) and other.call(song) }
+ end
+
+ def !
+ Criteria.new lambda{ |song| !self.call(song) }
+ end
+end
+
+class Collection
+ include Enumerable
+
+ def initialize(songs)
+ @songs = songs
+ end
+
+ def each
+ @songs.each { |song| yield song }
+ end
+
+ def self.parse(text)
+ songs = []
+ text.to_s.split("\n\n").each { |song| songs << Song.new( song ) }
+ self.new songs
+ 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)
+ filtered_songs = @songs.select { |song| criteria.call song }
+ Collection.new(filtered_songs)
+ end
+
+ def adjoin(other)
+ Collection.new(@songs | other.to_a)
+ end
+end