Решение на Втора задача от Димитър Илиев

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

Към профила на Димитър Илиев

Резултати

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

Код

class Array
def dc
self.map(&:downcase)
end
def split arg
self
end
alias has? include?
alias d_if delete_if
end
class String
alias dc downcase
def trim
self.gsub(/( ){2,}/,'')
end
end
class Collection
attr_accessor :songs
def initialize(songs_as_string,more_tags = {})
@songs = []
songs_as_string.trim.gsub(/(, )/,',').each_line do |line|
collect_song line.gsub(/\n/,'').split('.')
end
extend_tags more_tags
end
def collect_song n
@songs.push Song.new(n)
end
def find criteria
result = @songs.dup
criteria.each do |key,val|
val = val.dc
result.d_if {|n| not (n.send(key.to_sym).dc).split(',').has? val}
end
result
end
def extend_tags the_tags
the_tags.each do |artist,tags|
(find name: artist).each do |song|
song.add_tags tags
end
end
end
end
class Song
attr_accessor :name
attr_accessor :artist
attr_accessor :genre
attr_accessor :subgenre
attr_accessor :tags
def initialize(songs_arr)
@name = (songs_arr[0] || '')
@artist = (songs_arr[1] || '')
@genre = (songs_arr[2].split(',')[0] ||'')
@subgenre = (songs_arr[2].split(',')[1] ||'')
@tags = (songs_arr[3] || '').split(',')
add_tags [@genre,@subgenre]
end
def add_tags tags
@tags = (@tags << tags).flatten
end
def filter &block
block.call(self)
end
end

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

...F.FFFF.F.

Failures:

  1) Collection uses the genre and subgenre as tags
     Failure/Error: song(name: 'Miles Runs the Voodoo Down').tags.should include('jazz', 'fusion')
       expected ["weird", "Jazz", "Fusion"] to include "jazz" and "fusion"
       Diff:
       @@ -1,2 +1,2 @@
       -jazz
       +["weird", "Jazz", "Fusion"]
     # /tmp/d20111115-13548-1pq9der/spec.rb:49:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Collection can find songs by multiple tags
     Failure/Error: songs(tags: %w[popular violin]).map(&:name).should eq ['Eine Kleine Nachtmusik']
       
       expected: ["Eine Kleine Nachtmusik"]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Eine Kleine Nachtmusik"]
       +[]
     # /tmp/d20111115-13548-1pq9der/spec.rb:57:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Collection can find songs that don't have a tag
     Failure/Error: songs(tags: %w[weird cool!]).map(&:name).should eq ['Miles Runs the Voodoo Down']
       
       expected: ["Miles Runs the Voodoo Down"]
            got: []
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -["Miles Runs the Voodoo Down"]
       +[]
     # /tmp/d20111115-13548-1pq9der/spec.rb:61:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Collection can filter songs by a lambda
     Failure/Error: collection.find(options)
     NoMethodError:
       undefined method `dc' for #<Proc:0xaf0adc0>
     # /tmp/d20111115-13548-1pq9der/solution.rb:37:in `block in find'
     # /tmp/d20111115-13548-1pq9der/solution.rb:36:in `each'
     # /tmp/d20111115-13548-1pq9der/solution.rb:36:in `find'
     # /tmp/d20111115-13548-1pq9der/spec.rb:96:in `songs'
     # /tmp/d20111115-13548-1pq9der/spec.rb:65:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Collection adds the artist tags to the songs
     Failure/Error: songs(tags: 'polyphone').map(&:name).should =~ ['Toccata e Fuga', 'Goldberg Variations']
       expected collection contained:  ["Goldberg Variations", "Toccata e Fuga"]
       actual collection contained:    []
       the missing elements were:      ["Goldberg Variations", "Toccata e Fuga"]
     # /tmp/d20111115-13548-1pq9der/spec.rb:69:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Collection allows all criteria
     Failure/Error: collection.find(options)
     NoMethodError:
       undefined method `dc' for #<Proc:0xaf2fb34>
     # /tmp/d20111115-13548-1pq9der/solution.rb:37:in `block in find'
     # /tmp/d20111115-13548-1pq9der/solution.rb:36:in `each'
     # /tmp/d20111115-13548-1pq9der/solution.rb:36:in `find'
     # /tmp/d20111115-13548-1pq9der/spec.rb:96:in `songs'
     # /tmp/d20111115-13548-1pq9der/spec.rb:82:in `block (2 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.54444 seconds
12 examples, 6 failures

Failed examples:

rspec /tmp/d20111115-13548-1pq9der/spec.rb:48 # Collection uses the genre and subgenre as tags
rspec /tmp/d20111115-13548-1pq9der/spec.rb:56 # Collection can find songs by multiple tags
rspec /tmp/d20111115-13548-1pq9der/spec.rb:60 # Collection can find songs that don't have a tag
rspec /tmp/d20111115-13548-1pq9der/spec.rb:64 # Collection can filter songs by a lambda
rspec /tmp/d20111115-13548-1pq9der/spec.rb:68 # Collection adds the artist tags to the songs
rspec /tmp/d20111115-13548-1pq9der/spec.rb:76 # Collection allows all criteria

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

Димитър обнови решението на 30.10.2011 18:12 (преди около 13 години)

+class Array
+ def dc
+ self.map(&:downcase)
+ end
+ def split arg
+ self
+ end
+ alias has? include?
+ alias d_if delete_if
+end
+class String
+ alias dc downcase
+ def trim
+ self.gsub(/( ){2,}/,'')
+ end
+end
+
+class Collection
+
+ attr_accessor :songs
+
+ def initialize(songs_as_string,more_tags = {})
+ @songs = []
+ songs_as_string.trim.gsub(/(, )/,',').each_line do |line|
+ collect_song line.gsub(/\n/,'').split('.')
+ end
+ extend_tags more_tags
+ end
+
+ def collect_song n
+ @songs.push Song.new(n)
+ end
+
+ def find criteria
+ result = @songs.dup
+ criteria.each do |key,val|
+ val = val.dc
+ result.d_if {|n| not (n.send(key.to_sym).dc).split(',').has? val}
+ end
+ result
+ end
+
+ def extend_tags the_tags
+ the_tags.each do |artist,tags|
+ (find name: artist).each do |song|
+ song.add_tags tags
+ end
+ end
+ end
+end
+
+class Song
+ attr_accessor :name
+ attr_accessor :artist
+ attr_accessor :genre
+ attr_accessor :subgenre
+ attr_accessor :tags
+
+ def initialize(songs_arr)
+ @name = (songs_arr[0] || '')
+ @artist = (songs_arr[1] || '')
+ @genre = (songs_arr[2].split(',')[0] ||'')
+ @subgenre = (songs_arr[2].split(',')[1] ||'')
+ @tags = (songs_arr[3] || '').split(',')
+ add_tags [@genre,@subgenre]
+ end
+
+ def add_tags tags
+ @tags = (@tags << tags).flatten
+ end
+
+ def filter &block
+ block.call(self)
+ end
+end
  • Не спазваш идентация, което се опасявам, ти коства още една точка.
  • Не се пише (find name: artist).each, пише се find(name: artist).each. Така скобите са по-логично поставени.
  • collect_song е малко странен метод. Можеше просто да минеш с map
  • Monkey patch-а ти е много, много, много гаден. dc е лошо име. Това съобще да пипаш в Array и String е лоша идея. Това ти коства още една точка ;(
  • attr_accessor-ите могат да са на един ред.
  • Странно е Song да получава масив като аргумент. По-подхоящо щеше да е да даваш пет позицинно параметъра. В момента парсенето е разпределено между Collection и Song. Първото само прави един split, второто - допълнителни истории. В това няма смисъл.

Mokey patch-a беше за да спазя броя символи на ред и за да махна една допълнителна проверка. Друг вариянт е да започна да наименовам променливите със по 2букви. За индентацията това си е начина по който си пиша постоянно, но за курса ще се опитам да правя изключение. Още 1 нещо, collect_song можеби няма най-хубавото или или супер функционалност, но ми се струва че прави кода 1 идея по прегледен

По принцип идеята на ограниченията не е да ги заобикаляш така. Ако редът е дълъг, може да го разбиеш на няколко или да обърнеш {} към do/end. Monkey patch на вградени типове влиза в графата "не пасем трева" :)

Ако опира до индентацията, "така си пиша по принцип" е грешна позиция. Всеки път. Всеки език си има култура (или няколко) за това как да се идентира. Например, Ruby се идентира с два интервала. Python с четири. В C има няколко стандарта и тогава е важно да спазваш този, който се ползва в проекта, който пипаш. Но тези неща не са въпрос на лични предпочитания.