Решение на Втора задача от Румен Палетов

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

Към профила на Румен Палетов

Резултати

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

Код

module Filter
NAME = 1
ARTIST = 2
ALBUM = 4
end
module Operation
AND = 1
OR = 2
end
class Song
attr_reader :name
attr_reader :artist
attr_reader :album
def self.parse(text)
songDetails = text.split("\n")
Song.new(songDetails[0].strip, songDetails[1].strip, songDetails[2].strip)
end
def initialize(name, artist, album)
@name = name
@artist = artist
@album = album
end
def match?(type, title)
if type == Filter::NAME then @name == title
elsif type == Filter::ARTIST then @artist == title
elsif type == Filter::ALBUM then @album == title
else false
end
end
def fulfil?(filter)
if filter.leaf? then filter.negate != match?(filter.type, filter.title)
elsif filter.operation == Operation::AND
fulfil?(filter.left) && fulfil?(filter.right)
else fulfil?(filter.left) || fulfil?(filter.right)
end
end
def ==(song)
if !song then false
else @name == song.name && @artist == song.artist && @album == song.album
end
end
end
class Criteria
attr_reader :type
attr_reader :title
attr_reader :left
attr_reader :right
attr_reader :operation
attr_reader :negate
def self.name(title)
Criteria.new(Filter::NAME, title, false)
end
def self.artist(title)
Criteria.new(Filter::ARTIST, title, false)
end
def self.album(title)
Criteria.new(Filter::ALBUM, title, false)
end
def initialize(type = nil, title = nil, negate = nil)
@type = type
@title = title
@negate = negate
end
def set_children(left, right, operation)
@left = left
@right = right
@operation = operation
end
def leaf?
left == nil && right == nil
end
def &(criteria)
newCriteria = Criteria.new
newCriteria.set_children(self, criteria, Operation::AND)
newCriteria
end
def |(criteria)
newCriteria = Criteria.new
newCriteria.set_children(self, criteria, Operation::OR)
newCriteria
end
def !
Criteria.new(@type, @title, !@negate)
end
end
class Collection
include Enumerable
attr_reader :songs
def Collection.parse(text)
Collection.new(text.split("\n\n").map { |songText| Song.parse(songText) })
end
def initialize(songs)
@songs = songs
end
def each
@songs.each { |s| yield s }
end
def artists
@songs.map { |song| song.artist }.uniq
end
def albums
@songs.map { |song| song.album }.uniq
end
def names
@songs.map { |song| song.name }.uniq
end
def filter(criteria)
Collection.new(@songs.select { |song| song.fulfil?(criteria) })
end
def adjoin(collection)
Collection.new(@songs | collection.songs)
end
end

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

...........

Finished in 0.01019 seconds
11 examples, 0 failures

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

Румен обнови решението на 28.10.2012 22:05 (преди около 12 години)

+module Filter
+ NAME = 1
+ ARTIST = 2
+ ALBUM = 4
+end
+
+module Operation
+ AND = 1
+ OR = 2
+end
+
+class Song
+ attr_reader :name
+ attr_reader :artist
+ attr_reader :album
+
+ def self.parse(text)
+ songDetails = text.split("\n")
+ Song.new(songDetails[0].strip, songDetails[1].strip, songDetails[2].strip)
+ end
+
+ def initialize(name, artist, album)
+ @name = name
+ @artist = artist
+ @album = album
+ end
+
+ def match?(type, title)
+ if type == Filter::NAME then @name == title
+ elsif type == Filter::ARTIST then @artist == title
+ elsif type == Filter::ALBUM then @album == title
+ else false
+ end
+ end
+
+ def fulfil?(filter)
+ if filter.leaf? then filter.negate != match?(filter.type, filter.title)
+ elsif filter.operation == Operation::AND
+ fulfil?(filter.left) && fulfil?(filter.right)
+ else fulfil?(filter.left) || fulfil?(filter.right)
+ end
+ end
+
+ def ==(other)
+ !other ? false : @name == other && @artist == other && @album == other
+ end
+end
+
+class Criteria
+ attr_reader :type
+ attr_reader :title
+
+ attr_reader :left
+ attr_reader :right
+ attr_reader :operation
+ attr_reader :negate
+
+ def self.name(title)
+ Criteria.new(Filter::NAME, title, false)
+ end
+
+ def self.artist(title)
+ Criteria.new(Filter::ARTIST, title, false)
+ end
+
+ def self.album(title)
+ Criteria.new(Filter::ALBUM, title, false)
+ end
+
+ def initialize(type = nil, title = nil, negate = nil)
+ @type = type
+ @title = title
+ @negate = negate
+ end
+
+ def set_children(left, right, operation)
+ @left = left
+ @right = right
+ @operation = operation
+ end
+
+ def leaf?
+ left == nil && right == nil
+ end
+
+ def &(criteria)
+ newCriteria = Criteria.new
+ newCriteria.set_children(self, criteria, Operation::AND)
+ newCriteria
+ end
+
+ def |(criteria)
+ newCriteria = Criteria.new
+ newCriteria.set_children(self, criteria, Operation::OR)
+ newCriteria
+ end
+
+ def !
+ Criteria.new(@type, @title, !@negate)
+ end
+end
+
+class Collection
+ include Enumerable
+
+ attr_reader :songs
+
+ def Collection.parse(text)
+ Collection.new(text.split("\n\n").map { |songText| Song.parse(songText) })
+ end
+
+ def initialize(songs)
+ @songs = songs
+ end
+
+ def each
+ @songs.each { |s| yield s }
+ end
+
+ def artists
+ @songs.map { |song| song.artist }.uniq
+ end
+
+ def albums
+ @songs.map { |song| song.album }.uniq
+ end
+
+ def names
+ @songs.map { |song| song.name }.uniq
+ end
+
+ def filter(criteria)
+ Collection.new(@songs.select { |song| song.fulfil?(criteria) })
+ end
+
+ def adjoin(collection)
+ Collection.new(@songs | collection.songs)
+ end
+end

Румен обнови решението на 28.10.2012 22:15 (преди около 12 години)

module Filter
NAME = 1
ARTIST = 2
ALBUM = 4
end
module Operation
AND = 1
OR = 2
end
class Song
attr_reader :name
attr_reader :artist
attr_reader :album
def self.parse(text)
songDetails = text.split("\n")
Song.new(songDetails[0].strip, songDetails[1].strip, songDetails[2].strip)
end
def initialize(name, artist, album)
@name = name
@artist = artist
@album = album
end
def match?(type, title)
if type == Filter::NAME then @name == title
elsif type == Filter::ARTIST then @artist == title
elsif type == Filter::ALBUM then @album == title
else false
end
end
def fulfil?(filter)
if filter.leaf? then filter.negate != match?(filter.type, filter.title)
elsif filter.operation == Operation::AND
fulfil?(filter.left) && fulfil?(filter.right)
else fulfil?(filter.left) || fulfil?(filter.right)
end
end
- def ==(other)
- !other ? false : @name == other && @artist == other && @album == other
+ def ==(song)
+ if !song then false
+ else @name == song.name && @artist == song.artist && @album == song.album
+ end
end
end
class Criteria
attr_reader :type
attr_reader :title
attr_reader :left
attr_reader :right
attr_reader :operation
attr_reader :negate
def self.name(title)
Criteria.new(Filter::NAME, title, false)
end
def self.artist(title)
Criteria.new(Filter::ARTIST, title, false)
end
def self.album(title)
Criteria.new(Filter::ALBUM, title, false)
end
def initialize(type = nil, title = nil, negate = nil)
@type = type
@title = title
@negate = negate
end
def set_children(left, right, operation)
@left = left
@right = right
@operation = operation
end
def leaf?
left == nil && right == nil
end
def &(criteria)
newCriteria = Criteria.new
newCriteria.set_children(self, criteria, Operation::AND)
newCriteria
end
def |(criteria)
newCriteria = Criteria.new
newCriteria.set_children(self, criteria, Operation::OR)
newCriteria
end
def !
Criteria.new(@type, @title, !@negate)
end
end
class Collection
include Enumerable
attr_reader :songs
def Collection.parse(text)
Collection.new(text.split("\n\n").map { |songText| Song.parse(songText) })
end
def initialize(songs)
@songs = songs
end
def each
@songs.each { |s| yield s }
end
def artists
@songs.map { |song| song.artist }.uniq
end
def albums
@songs.map { |song| song.album }.uniq
end
def names
@songs.map { |song| song.name }.uniq
end
def filter(criteria)
Collection.new(@songs.select { |song| song.fulfil?(criteria) })
end
def adjoin(collection)
Collection.new(@songs | collection.songs)
end
end

Това с Filter и Operation е C код. Ужасно неприемливо при това. Изумен съм, че си успял да се впишеш в ограниченията, предвид че трябва да пазят точно от такива опити.

Вместо да го правиш така, опитай да създадеш малка йерархия от критерии. Пробвай да направиш по един наследни за всеки вид филтър. После пробвай да видиш дали не могат да намалиш класовете по някакъв начин.

Също така, не спазваш конвенции на места. И не съм убеден дали имаш правописни греши или ползваш британски правопис.

При всички случаи, за момента вървиш към някакво количество наказателни точки.

Съгласен съм за C кода, просто ми хареса идеята да си направя критериите като дърво :).

Какво имаш в предвид под наследник за всеки вид филтър. Един клас с два наследника – един за & и един за | или нещо друго?

Може ли да те помоля да конкретизираш кои конвенции точно не спазвам, защото не ми е много ясно.

И мерси за обратната връзка ;).

Бъркаш нещо в имената. Няма да ти кажа какво, искам да го откриеш сам.

Отделно, в match? и fulfil? не ти достига място да имплементираш методите така, както искаш. Ако напишеш if-овете както трябва, няма да се съберат в ограниченията. Това трябва да те наведе на мисълта, че правиш нещо грешно.

Иначе, имах предвид, че можеш да направиш Criteria като йерархия. Няма да ти казвам как, обаче. Само ще ти подскажа, че имплементацията на Collection#filter трябва да изглежда така:

Collection.new @songs.select { |song| criteria.met_by? song }