Пламен обнови решението на 31.10.2012 07:46 (преди около 12 години)
+class Song
+ attr_accessor :name, :artist, :album
+
+ def initialize(name, artist, album)
+ @name, @artist, @album = name, artist, album
+ end
+end
+
+class Collection
+ include Enumerable
+
+ def initialize(songs)
+ @songs = songs
+ end
+
+ def names
+ (map &:name).uniq
+ end
+
+ def artists
+ (map &:artist).uniq
+ end
+
+ def albums
+ (map &:album).uniq
+ end
+
+ def each(&block)
+ @songs.each &block
+ end
+
+ def filter(criteria)
+ Collection.new @songs.select &criteria
+ end
+
+ def adjoin(other)
+ Collection.new (to_a + other.to_a).uniq
+ end
+
+ def Collection.parse(text)
+ song_paragraphs = text.lines('').map &:strip
+ songs = song_paragraphs.map { |song| Song.new *song.split("\n") }
+
+ Collection.new songs
+ end
+end
+
+class Criteria
+ def initialize(criteria)
+ @criteria = criteria
+ end
+
+ def &(other)
+ Criteria.new Proc.new { |song| to_proc[song] && other.to_proc[song] }
+ end
+
+ def |(other)
+ Criteria.new Proc.new { |song| to_proc[song] || other.to_proc[song] }
+ end
+
+ def !
+ Criteria.new Proc.new { |song| !to_proc[song] }
+ end
+
+ def Criteria.name(name)
+ Criteria.new Proc.new { |song| song.name == name }
+ end
+
+ def Criteria.artist(artist)
+ Criteria.new Proc.new { |song| song.artist == artist }
+ end
+
+ def Criteria.album(album)
+ Criteria.new Proc.new { |song| song.album == album }
+ end
+
+ def to_proc
+ @criteria
+ end
+end