Решение на Трета задача от Емилиан Станков

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

Към профила на Емилиан Станков

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 40 успешни тест(а)
  • 4 неуспешни тест(а)

Код

module RBFS
class File
attr_accessor :data
attr_reader :data_type
def initialize(data = nil)
set_file_data(data)
end
def data=(data)
set_file_data(data)
end
def serialize
"#{@data_type}:#{@data}"
end
def self.parse(string_data)
data_type, data = string_data.split(':')[0], string_data.split(':', 2)[1]
case data_type.to_sym
when :boolean then File.new(data == "true")
when :nil then File.new()
when :number then File.new(Float(data))
when :symbol then File.new(data.to_sym)
when :string then File.new(data)
end
end
def set_file_data(data)
@data = data
case @data
when FalseClass, TrueClass then @data_type = :boolean
when NilClass then @data_type = :nil
when Fixnum, Float then @data_type = :number
when String then @data_type = :string
when Symbol then @data_type = :symbol
end
end
end
class Directory
attr_reader :files
attr_reader :directories
def initialize
@files = {}
@directories = {}
end
def add_file(name, file)
@files[name] = file
end
def add_directory(name, directory = Directory.new)
@directories[name] = directory
end
def [](name)
directories.has_key?(name) ? directories[name] : files[name]
end
def serialize
result = @files.each_with_object(["#{@files.size.to_s}:"]) do |(name, file), result|
result << "#{name}:#{file.serialize.size.to_s}:#{file.serialize}"
end
result << "#{@directories.size.to_s}:"
@directories.each_with_object(result) do |(name, dir), result|
result << "#{name}:#{dir.serialize.size.to_s}:#{dir.serialize}"
end
result.join
end
def self.parse(string_data)
end
end
end

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

..........FFFF..............................

Failures:

  1) RBFS Directory serialization ::parse can parse empty directories
     Failure/Error: expect(parsed_directory.files      ).to eq({})
     NoMethodError:
       undefined method `files' for nil:NilClass
     # /tmp/d20141111-26053-1txlq7u/spec.rb:103:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) RBFS Directory serialization ::parse can parse directories with files
     Failure/Error: expect(parsed_directory.files.size     ).to eq    2
     NoMethodError:
       undefined method `files' for nil:NilClass
     # /tmp/d20141111-26053-1txlq7u/spec.rb:110:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) RBFS Directory serialization ::parse can parse directory trees without files
     Failure/Error: expect(parsed_directory['dir1']        ).to be_an RBFS::Directory
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20141111-26053-1txlq7u/spec.rb:119:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) RBFS Directory serialization ::parse can parse directories recursively
     Failure/Error: expect(parsed_directory.files.size     ).to eq 2
     NoMethodError:
       undefined method `files' for nil:NilClass
     # /tmp/d20141111-26053-1txlq7u/spec.rb:127:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.0418 seconds
44 examples, 4 failures

Failed examples:

rspec /tmp/d20141111-26053-1txlq7u/spec.rb:100 # RBFS Directory serialization ::parse can parse empty directories
rspec /tmp/d20141111-26053-1txlq7u/spec.rb:107 # RBFS Directory serialization ::parse can parse directories with files
rspec /tmp/d20141111-26053-1txlq7u/spec.rb:116 # RBFS Directory serialization ::parse can parse directory trees without files
rspec /tmp/d20141111-26053-1txlq7u/spec.rb:124 # RBFS Directory serialization ::parse can parse directories recursively

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

Емилиан обнови решението на 31.10.2014 13:34 (преди около 10 години)

+module RBFS
+ class File
+ attr_accessor :data
+ attr_reader :data_type
+
+ def initialize(data = nil)
+ set_file_data(data)
+ end
+
+ def data=(data)
+ reset_file_data(data)
+ end
+
+ def data_type
+ @data_type
+ end
+
+ def serialize
+ "#{@data_type}:#{@data}"
+ end
+
+ def File.parse(string_data)
+ case string_data.split(':')[0].to_sym
+ when :boolean then boolean_file(string_data.split(':')[1])
+ when :nil then File.new()
+ when :number then File.new(Float(string_data.split(':')[1]))
+ when :symbol then File.new(string_data.split(':')[1].to_sym)
+ when :string then File.new(string_data.split(':')[1])
+ end
+ end
+
+ def File.boolean_file(data)
+ return File.new(false) if data == "false"
+ return File.new(true) if data == "true"
+ end
+
+ def set_file_data(data)
+ @data = data
+ @data_type = :boolean if @data.class == FalseClass or TrueClass
+ @data_type = :nil if @data.class == NilClass
+ @data_type = :number if @data.class == Fixnum or @data.class == Float
+ @data_type = :string if @data.class == String
+ @data_type = :symbol if @data.class == Symbol
+ end
+
+ alias :reset_file_data :set_file_data
+ end
+
+
+ class Directory
+ attr_reader :files
+ attr_reader :directories
+
+ def initialize
+ @files = {}
+ @directories = {}
+ end
+
+ def add_file(name, file)
+ @files[name] = file
+ end
+
+ def add_directory(name, directory)
+ @directories[name] = directory
+ end
+
+ def [](name)
+ end
+
+ def serialize
+ end
+
+ def Directory.parse(string_data)
+ end
+ end
+end

Здравей :)

Ти си първият, предал решение, поздравления! :)

Осъзнавам, че най-вероятно все още не си приключил с решаването, но ще оставя няколко коментара, които се надявам да помогнат:

  • Виждам две излишни неща:
    • def data_type == attr_reader data_type
    • alias-a, в случая, ми се струва ненужен. Името set_file_data не изключва възможността да се използва повторно.
  • Може да се възползваш от това, че няма да ви подаваме невалидни типове данни, за парсването на булевите стойности.

Освен това, вдигнахме ограничението за редове в метод - вече можеш да си използваш case в set_file_data и да отделиш повторението в parse.

Емилиан обнови решението на 31.10.2014 18:44 (преди около 10 години)

module RBFS
class File
attr_accessor :data
attr_reader :data_type
def initialize(data = nil)
set_file_data(data)
end
def data=(data)
- reset_file_data(data)
+ set_file_data(data)
end
- def data_type
- @data_type
- end
-
def serialize
"#{@data_type}:#{@data}"
end
def File.parse(string_data)
- case string_data.split(':')[0].to_sym
- when :boolean then boolean_file(string_data.split(':')[1])
+ data_type, data = string_data.split(':')[0], string_data.split(':')[1]
+ case data_type.to_sym
+ when :boolean then boolean_file(data)
when :nil then File.new()
- when :number then File.new(Float(string_data.split(':')[1]))
- when :symbol then File.new(string_data.split(':')[1].to_sym)
- when :string then File.new(string_data.split(':')[1])
+ when :number then File.new(Float(data))
+ when :symbol then File.new(data.to_sym)
+ when :string then File.new(data)
end
end
def File.boolean_file(data)
return File.new(false) if data == "false"
return File.new(true) if data == "true"
end
def set_file_data(data)
@data = data
- @data_type = :boolean if @data.class == FalseClass or TrueClass
- @data_type = :nil if @data.class == NilClass
- @data_type = :number if @data.class == Fixnum or @data.class == Float
- @data_type = :string if @data.class == String
- @data_type = :symbol if @data.class == Symbol
+ case @data
+ when FalseClass, TrueClass then @data_type = :boolean
+ when NilClass then @data_type = :nil
+ when Fixnum, Float then @data_type = :number
+ when String then @data_type = :string
+ when Symbol then @data_type = :symbol
+ end
end
-
- alias :reset_file_data :set_file_data
end
class Directory
attr_reader :files
attr_reader :directories
def initialize
@files = {}
@directories = {}
end
def add_file(name, file)
@files[name] = file
end
- def add_directory(name, directory)
+ def add_directory(name, directory = Directory.new)
@directories[name] = directory
end
def [](name)
+ return directories[name] if directories.has_key? name
+ return files[name] if files.has_key? name
+ nil
end
def serialize
+ result = @files.each_with_object(["#{@files.size.to_s}:"]) do |(name, file), result|
+ result << "#{name}:#{file.serialize.size.to_s}:#{file.serialize}"
+ end
+ result << "#{@directories.size.to_s}:"
+ @directories.each_with_object(result) do |(name, dir), result|
+ result << "#{name}:#{dir.serialize.size.to_s}:#{dir.serialize}"
+ end
+ result.join
end
def Directory.parse(string_data)
end
end
end

Окей, още малко късновечерни/раннонощтни коментарчета. :)

return File.new(false) if data == "false"
return File.new(true) if data == "true"

Това не ми харесва особено. Има начин да го направиш на един ред, без return и само с едно викане на File.new.

return directories[name] if directories.has_key? name
return files[name]       if files.has_key? name
nil

Това също може да се случи на един ред. Подсказка - hash[name] връща nil, ако няма намерен елемент с такъв ключ. Още една подсказка - nil е едно от двете неща, които се считат за false.

Тези each_with_object-и ужасно много ми напомнят за map-ове. Ако пробваш да го направиш с map със сигурност ще останеш доволен. :)

Освен това, постарай се да не извикваш многократно serialize - все пак може папката или файлът да са доста големи и ще вършиш двойно повече работа. Не е нужно всичко да го направиш в един метод, може да ги разделиш. Същото се отнася и за сплитването при parse.

Ииии парсването ти на файлове няма да работи в един случай, показан като пример в условието на задачата. :)

Емилиан обнови решението на 06.11.2014 17:01 (преди около 10 години)

module RBFS
class File
attr_accessor :data
attr_reader :data_type
def initialize(data = nil)
set_file_data(data)
end
def data=(data)
set_file_data(data)
end
def serialize
"#{@data_type}:#{@data}"
end
- def File.parse(string_data)
- data_type, data = string_data.split(':')[0], string_data.split(':')[1]
+ def self.parse(string_data)
+ data_type, data = string_data.split(':')[0], string_data.split(':', 2)[1]
case data_type.to_sym
- when :boolean then boolean_file(data)
+ when :boolean then File.new(data == "true")
when :nil then File.new()
when :number then File.new(Float(data))
when :symbol then File.new(data.to_sym)
when :string then File.new(data)
end
end
- def File.boolean_file(data)
- return File.new(false) if data == "false"
- return File.new(true) if data == "true"
- end
-
def set_file_data(data)
@data = data
case @data
when FalseClass, TrueClass then @data_type = :boolean
when NilClass then @data_type = :nil
when Fixnum, Float then @data_type = :number
when String then @data_type = :string
when Symbol then @data_type = :symbol
end
end
end
class Directory
attr_reader :files
attr_reader :directories
def initialize
@files = {}
@directories = {}
end
def add_file(name, file)
@files[name] = file
end
def add_directory(name, directory = Directory.new)
@directories[name] = directory
end
def [](name)
- return directories[name] if directories.has_key? name
- return files[name] if files.has_key? name
- nil
+ directories.has_key?(name) ? directories[name] : files[name]
end
def serialize
result = @files.each_with_object(["#{@files.size.to_s}:"]) do |(name, file), result|
result << "#{name}:#{file.serialize.size.to_s}:#{file.serialize}"
end
result << "#{@directories.size.to_s}:"
@directories.each_with_object(result) do |(name, dir), result|
result << "#{name}:#{dir.serialize.size.to_s}:#{dir.serialize}"
end
result.join
end
- def Directory.parse(string_data)
+ def self.parse(string_data)
end
end
end