Христо обнови решението на 31.10.2012 16:09 (преди около 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 :rule
+
+ def initialize(&rule)
+ @rule = rule
+ end
+
+ def self.name(name)
+ new { |song| song.name == name }
+ end
+
+ def self.artist(artist)
+ new { |song| song.artist == artist }
+ end
+
+ def self.album(album)
+ new { |song| song.album == album }
+ end
+
+ def &(other)
+ Criteria.new do |song|
+ self.rule.call(song) && other.rule.call(song)
+ end
+ end
+
+ def |(other)
+ Criteria.new do |song|
+ self.rule.call(song) || other.rule.call(song)
+ end
+ end
+
+ def !
+ Criteria.new { |song| !self.rule.call(song) }
+ end
+end
+
+class Collection
+ include Enumerable
+
+ attr_reader :names, :artists, :albums, :songs
+
+ def initialize(songs)
+ @songs = songs
+
+ @names = @songs.map(&:name).uniq
+ @artists = @songs.map(&:artist).uniq
+ @albums = @songs.map(&:album).uniq
+ end
+
+ def self.parse(text)
+ songs = text.split("\n\n").map do |lines|
+ Song.new *lines.split("\n")
+ end
+
+ new songs
+ end
+
+ def filter(criteria)
+ Collection.new @songs.select(&criteria.rule)
+ end
+
+ def adjoin(other)
+ Collection.new (@songs + other.songs).uniq
+ end
+
+ def each
+ @songs.each { |song| yield song }
+ end
+end