Решение на Втора задача от Евгени Кунев

Обратно към всички решения

Към профила на Евгени Кунев

Резултати

  • 6 точки от тестове
  • 1 бонус точка
  • 7 точки общо
  • 12 успешни тест(а)
  • 0 неуспешни тест(а)

Код

class Song
attr_accessor :name, :artist,
:genre, :subgenre,
:tags
def initialize(song_hash)
@name = song_hash[:name].strip
@artist = song_hash[:artist].strip
@genre = song_hash[:genre].strip
@subgenre = song_hash[:subgenre].strip if song_hash[:subgenre]
@tags = song_hash[:tags].map!{|tag| tag.strip}
end
def matches_criteria?(criteria_hash)
criteria_hash.each do |attribute, value|
return false unless matches_criterion? attribute, value
end
true
end
def matches_criterion?(attribute, value)
value = Array(value)
if attribute == :filter
return value.all? { |filter| filter.(self) }
end
if attribute == :tags
match_positive_tags?(value) and match_negative_tags?(value)
else
value.include? attribute.to_proc.(self)
end
end
def match_positive_tags?(tags)
tags.select { |tag| not tag.end_with?'!' }.all?{ |tag| @tags.include?tag }
end
def match_negative_tags?(tags)
tags.select { |tag| tag.end_with?'!' }.none?{ |tag| @tags.include?tag.chop }
end
end
class Collection
attr_reader :songs
def initialize(songs_string, artist_tags)
@songs = songs_string.lines.map do |line|
Song.new Collection.song_line_to_hash line, artist_tags
end
end
def find(criteria)
@songs.select { |song| song.matches_criteria? criteria }
end
private
def self.song_line_to_hash(line, artist_tags)
values = line.split('.').map{|str| str.strip}
pairs = [ :name, :artist, :genre_subgenre, :tags ].zip(values)
fix_hash(Hash[pairs], artist_tags)
end
def self.fix_hash(song_hash, artist_tags)
song_hash[:genre_subgenre] = song_hash[:genre_subgenre].split /\s*,\s*/
song_hash[:genre], song_hash[:subgenre] = song_hash[:genre_subgenre]
song_hash[:tags] = song_hash[:tags] ? song_hash[:tags].split(',') : []
song_hash[:tags] << song_hash[:genre].downcase if song_hash[:genre]
song_hash[:tags] << song_hash[:subgenre].downcase if song_hash[:subgenre]
song_hash[:tags] += (artist_tags[song_hash[:artist]] or [])
song_hash
end
end

Лог от изпълнението

............

Finished in 0.54944 seconds
12 examples, 0 failures

История (1 версия и 2 коментара)

Евгени обнови решението на 28.10.2011 00:56 (преди над 12 години)

+class Song
+ attr_accessor :name, :artist,
+ :genre, :subgenre,
+ :tags
+
+ def initialize(song_hash)
+ @name = song_hash[:name].strip
+ @artist = song_hash[:artist].strip
+ @genre = song_hash[:genre].strip
+ @subgenre = song_hash[:subgenre].strip if song_hash[:subgenre]
+ @tags = song_hash[:tags].map!{|tag| tag.strip}
+ end
+
+ def matches_criteria?(criteria_hash)
+ criteria_hash.each do |attribute, value|
+ return false unless matches_criterion? attribute, value
+ end
+ true
+ end
+
+ def matches_criterion?(attribute, value)
+ value = Array(value)
+ if attribute == :filter
+ return value.all? { |filter| filter.(self) }
+ end
+ if attribute == :tags
+ match_positive_tags?(value) and match_negative_tags?(value)
+ else
+ value.include? attribute.to_proc.(self)
+ end
+ end
+
+ def match_positive_tags?(tags)
+ tags.select { |tag| not tag.end_with?'!' }.all?{ |tag| @tags.include?tag }
+ end
+
+ def match_negative_tags?(tags)
+ tags.select { |tag| tag.end_with?'!' }.none?{ |tag| @tags.include?tag.chop }
+ end
+end
+
+class Collection
+ attr_reader :songs
+
+ def initialize(songs_string, artist_tags)
+ @songs = songs_string.lines.map do |line|
+ Song.new Collection.song_line_to_hash line, artist_tags
+ end
+ end
+
+ def find(criteria)
+ @songs.select { |song| song.matches_criteria? criteria }
+ end
+
+ private
+
+ def self.song_line_to_hash(line, artist_tags)
+ values = line.split('.').map{|str| str.strip}
+ pairs = [ :name, :artist, :genre_subgenre, :tags ].zip(values)
+ fix_hash(Hash[pairs], artist_tags)
+ end
+
+ def self.fix_hash(song_hash, artist_tags)
+ song_hash[:genre_subgenre] = song_hash[:genre_subgenre].split /\s*,\s*/
+ song_hash[:genre], song_hash[:subgenre] = song_hash[:genre_subgenre]
+ song_hash[:tags] = song_hash[:tags] ? song_hash[:tags].split(',') : []
+ song_hash[:tags] << song_hash[:genre].downcase if song_hash[:genre]
+ song_hash[:tags] << song_hash[:subgenre].downcase if song_hash[:subgenre]
+ song_hash[:tags] += (artist_tags[song_hash[:artist]] or [])
+ song_hash
+ end
+end