Решение на Трета задача от Атанас Димитров

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

Към профила на Атанас Димитров

Резултати

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

Код

module RBFS
class File
attr_accessor :data
def initialize(data = nil)
@data = data
end
def data_type
if data.is_a?(Numeric) then :number
elsif data.is_a?(String) then :string
elsif data.is_a?(Symbol) then :symbol
elsif data.is_a?(NilClass) then :nil
else :boolean
end
end
def serialize
"#{data_type}:#{data}"
end
def self.parse(string_data)
type_data, data = string_data.split(':')
if type_data == 'string' then File.new(data)
elsif type_data == 'symbol' then File.new(data.to_sym)
elsif type_data == 'nil' then File.new
elsif data.include?('.') then File.new(data.to_f)
elsif type_data == 'number' then File.new(data.to_i)
else File.new(data == 'true')
end
end
def self.parse_multiple_files(string_data)
files = {}
file_counter = string_data.partition(':').first.to_i
not_parsed = string_data.partition(':').last
file_counter.times do
file_name, file_size, tail = not_parsed.split(':', 3)
files[file_name] = File.parse tail[0, file_size.to_i]
not_parsed = tail[file_size.to_i, not_parsed.size]
end
[files, not_parsed]
end
end
class Directory
def initialize(files = {}, directories = {})
@folder = {files: files, directories: directories}
end
def add_file(name, file = File.new)
@folder[:files][name] = file
end
def add_directory(name, directory = Directory.new)
@folder[:directories][name] = directory
end
def files
@folder[:files]
end
def directories
@folder[:directories]
end
def [](name)
directories.fetch(name, files[name])
end
def serialize
serialized = ''
serialized.concat(files.size.to_s).concat(':')
files.each_pair do |key, value|
serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized.concat(directories.size.to_s).concat(':')
directories.each_pair do |key, value|
serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized
end
def self.parse(string_data)
folders, (files, not_parsed) ={}, File.parse_multiple_files(string_data)
folder_counter = not_parsed.partition(':').first.to_i
not_parsed = not_parsed.partition(':').last
folder_counter.times do
folder_name, folder_size, tail = not_parsed.split(':', 3)
folders[folder_name] = Directory.parse(tail[0, folder_size.to_i])
not_parsed = tail[folder_size.to_i, not_parsed.size]
end
Directory.new(files, folders)
end
end
end

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

............................F...............

Failures:

  1) RBFS File data type string can parse a string with colons
     Failure/Error: expect(file.data     ).to eq 'Hay :)'
       
       expected: "Hay :)"
            got: "Hay "
       
       (compared using ==)
     # /tmp/d20141111-26053-12t02hm/spec.rb:257: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.0488 seconds
44 examples, 1 failure

Failed examples:

rspec /tmp/d20141111-26053-12t02hm/spec.rb:254 # RBFS File data type string can parse a string with colons

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

Атанас обнови решението на 03.11.2014 10:28 (преди над 9 години)

+module RBFS
+
+ class File
+ attr_accessor :data
+
+ def initialize(data = nil)
+ @data = data
+ end
+
+ def data_type()
+ case
+ when data.is_a?(Numeric) then :number
+ when data.is_a?(String) then :string
+ when data.is_a?(Symbol) then :symbol
+ when data.is_a?(NilClass) then :nil
+ else :boolean
+ end
+ end
+
+ def serialize()
+ data_type.to_s.+ ':' + data.to_s
+ end
+
+ def File.parse(string_data)
+ type_data, data = string_data.partition(':').first, string_data.partition(':').last
+ case
+ when type_data == 'string' then File.new(data)
+ when type_data == 'symbol' then File.new(data.to_sym)
+ when data == 'true' then File.new(true)
+ when data == 'false' then File.new(false)
+ when data.include?('.') then File.new(data.to_f)
+ when type_data == 'number' then File.new(data.to_i)
+ else File.new(nil)
+ end
+ end
+
+ def File.multi_parse(string_data)
+ files = {}
+ file_counter = string_data.partition(':').first.to_i
+ not_parsed = string_data.partition(':').last
+ file_counter.times do
+ file_name, file_size, tail = not_parsed.split(':', 3)
+ files[file_name] = File.parse tail[0, file_size.to_i]
+ not_parsed = tail[file_size.to_i, not_parsed.size]
+ end
+ [files, not_parsed]
+ end
+ end
+
+
+ class Directory
+ def initialize(files = {}, directories = {})
+ @folder = {files: files, directories: directories}
+ end
+
+ def add_file(name, file = File.new)
+ @folder[:files][name] = file
+ end
+
+ def add_directory(name, directory = Directory.new)
+ @folder[:directories][name] = directory
+ end
+
+ def files()
+ @folder[:files]
+ end
+
+ def directories()
+ @folder[:directories]
+ end
+
+ def [](name)
+ directories.fetch(name, files[name])
+ end
+
+ def serialize()
+ serialized = ''
+
+ serialized.concat(files.size.to_s).concat(':')
+ files.each_pair do |key, value|
+ serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
+ end
+
+ serialized.concat(directories.size.to_s).concat(':')
+ directories.each_pair do |key, value|
+ serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
+ end
+
+ serialized
+ end
+
+ def Directory.parse(string_data)
+ folders, (files, not_parsed) ={}, File.multi_parse(string_data)
+ folder_counter = not_parsed.partition(':').first.to_i
+ not_parsed = not_parsed.partition(':').last
+ folder_counter.times do
+ folder_name, folder_size, tail = not_parsed.split(':', 3)
+ folders[folder_name] = Directory.parse(tail[0, folder_size.to_i])
+ not_parsed = tail[folder_size.to_i, not_parsed.size]
+ end
+ Directory.new(files, folders)
+ end
+ end
+end

Атанас обнови решението на 03.11.2014 23:29 (преди над 9 години)

module RBFS
class File
attr_accessor :data
def initialize(data = nil)
@data = data
end
def data_type()
- case
- when data.is_a?(Numeric) then :number
- when data.is_a?(String) then :string
- when data.is_a?(Symbol) then :symbol
- when data.is_a?(NilClass) then :nil
- else :boolean
+ if data.is_a?(Numeric) then :number
+ elsif data.is_a?(String) then :string
+ elsif data.is_a?(Symbol) then :symbol
+ elsif data.is_a?(NilClass) then :nil
+ else :boolean
end
end
def serialize()
data_type.to_s.+ ':' + data.to_s
end
- def File.parse(string_data)
+ def self.parse(string_data)
type_data, data = string_data.partition(':').first, string_data.partition(':').last
- case
- when type_data == 'string' then File.new(data)
- when type_data == 'symbol' then File.new(data.to_sym)
- when data == 'true' then File.new(true)
- when data == 'false' then File.new(false)
- when data.include?('.') then File.new(data.to_f)
- when type_data == 'number' then File.new(data.to_i)
- else File.new(nil)
+ if type_data == 'string' then File.new(data)
+ elsif type_data == 'symbol' then File.new(data.to_sym)
+ elsif data == 'true' then File.new(true)
+ elsif data == 'false' then File.new(false)
+ elsif data.include?('.') then File.new(data.to_f)
+ elsif type_data == 'number' then File.new(data.to_i)
+ else File.new(nil)
end
end
- def File.multi_parse(string_data)
+ def self.multi_parse(string_data)
files = {}
file_counter = string_data.partition(':').first.to_i
not_parsed = string_data.partition(':').last
file_counter.times do
file_name, file_size, tail = not_parsed.split(':', 3)
files[file_name] = File.parse tail[0, file_size.to_i]
not_parsed = tail[file_size.to_i, not_parsed.size]
end
[files, not_parsed]
end
end
class Directory
def initialize(files = {}, directories = {})
@folder = {files: files, directories: directories}
end
def add_file(name, file = File.new)
@folder[:files][name] = file
end
def add_directory(name, directory = Directory.new)
@folder[:directories][name] = directory
end
def files()
@folder[:files]
end
def directories()
@folder[:directories]
end
def [](name)
directories.fetch(name, files[name])
end
def serialize()
serialized = ''
serialized.concat(files.size.to_s).concat(':')
files.each_pair do |key, value|
serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
end
serialized.concat(directories.size.to_s).concat(':')
directories.each_pair do |key, value|
serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
end
serialized
end
- def Directory.parse(string_data)
+ def self.parse(string_data)
folders, (files, not_parsed) ={}, File.multi_parse(string_data)
folder_counter = not_parsed.partition(':').first.to_i
not_parsed = not_parsed.partition(':').last
folder_counter.times do
folder_name, folder_size, tail = not_parsed.split(':', 3)
folders[folder_name] = Directory.parse(tail[0, folder_size.to_i])
not_parsed = tail[folder_size.to_i, not_parsed.size]
end
Directory.new(files, folders)
end
end
end

Здрасти, като цяло добре си се справил с условието. Ето няколко забележки:

  • Главният проблем на решението (както вероятно и сам си се досетил) е няколкото методи - стени от код. Не малка част от кода вътре е неидиоматичен само и само да се впише в ограниченията. Множествено присвояване, whitespaces, доста процедурен подход, много междинни променливи. Всичко щеше да стане по-лесно, красиво и безболезнено, ако беше изнесъл логиката за [де]сериализацията в отделен клас. Щеше да реши и проблема с това къде трябва да стои multi_parse (което не е и най-доброто име).
  • parse във File можеше да има по-малко случаи и да изглежда по-консистентно.
  • Не слагай скоби при дефинирането и/или викането на методи без аргументи.
  • Нагаждал си някаква неща с partition, методът, който си търсил, е split с един аргумент.
  • Можеше да интерполираш нещата във File#serialize както на другите места. Също при интерполация имплицитно се вика to_s, не е нужно да го правиш изрично.

Атанас обнови решението на 10.11.2014 15:10 (преди над 9 години)

module RBFS
class File
attr_accessor :data
def initialize(data = nil)
@data = data
end
- def data_type()
+ def data_type
if data.is_a?(Numeric) then :number
elsif data.is_a?(String) then :string
elsif data.is_a?(Symbol) then :symbol
elsif data.is_a?(NilClass) then :nil
else :boolean
end
end
- def serialize()
- data_type.to_s.+ ':' + data.to_s
+ def serialize
+ "#{data_type}:#{data}"
end
def self.parse(string_data)
- type_data, data = string_data.partition(':').first, string_data.partition(':').last
+ type_data, data = string_data.split(':')
if type_data == 'string' then File.new(data)
elsif type_data == 'symbol' then File.new(data.to_sym)
- elsif data == 'true' then File.new(true)
- elsif data == 'false' then File.new(false)
+ elsif type_data == 'nil' then File.new
elsif data.include?('.') then File.new(data.to_f)
elsif type_data == 'number' then File.new(data.to_i)
- else File.new(nil)
+ else File.new(data == 'true')
end
end
def self.multi_parse(string_data)
files = {}
file_counter = string_data.partition(':').first.to_i
not_parsed = string_data.partition(':').last
file_counter.times do
file_name, file_size, tail = not_parsed.split(':', 3)
files[file_name] = File.parse tail[0, file_size.to_i]
not_parsed = tail[file_size.to_i, not_parsed.size]
end
[files, not_parsed]
end
end
class Directory
def initialize(files = {}, directories = {})
@folder = {files: files, directories: directories}
end
def add_file(name, file = File.new)
@folder[:files][name] = file
end
def add_directory(name, directory = Directory.new)
@folder[:directories][name] = directory
end
- def files()
+ def files
@folder[:files]
end
- def directories()
+ def directories
@folder[:directories]
end
def [](name)
directories.fetch(name, files[name])
end
- def serialize()
+ def serialize
serialized = ''
serialized.concat(files.size.to_s).concat(':')
files.each_pair do |key, value|
- serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
+ serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized.concat(directories.size.to_s).concat(':')
directories.each_pair do |key, value|
- serialized.concat "#{key.to_s}:#{value.serialize.length}:#{value.serialize}"
+ serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized
end
def self.parse(string_data)
folders, (files, not_parsed) ={}, File.multi_parse(string_data)
folder_counter = not_parsed.partition(':').first.to_i
not_parsed = not_parsed.partition(':').last
folder_counter.times do
folder_name, folder_size, tail = not_parsed.split(':', 3)
folders[folder_name] = Directory.parse(tail[0, folder_size.to_i])
not_parsed = tail[folder_size.to_i, not_parsed.size]
end
Directory.new(files, folders)
end
end
-end
+end

Атанас обнови решението на 10.11.2014 15:25 (преди над 9 години)

module RBFS
class File
attr_accessor :data
def initialize(data = nil)
@data = data
end
def data_type
if data.is_a?(Numeric) then :number
elsif data.is_a?(String) then :string
elsif data.is_a?(Symbol) then :symbol
elsif data.is_a?(NilClass) then :nil
else :boolean
end
end
def serialize
"#{data_type}:#{data}"
end
def self.parse(string_data)
type_data, data = string_data.split(':')
if type_data == 'string' then File.new(data)
elsif type_data == 'symbol' then File.new(data.to_sym)
elsif type_data == 'nil' then File.new
elsif data.include?('.') then File.new(data.to_f)
elsif type_data == 'number' then File.new(data.to_i)
else File.new(data == 'true')
end
end
- def self.multi_parse(string_data)
+ def self.parse_multiple_files(string_data)
files = {}
file_counter = string_data.partition(':').first.to_i
not_parsed = string_data.partition(':').last
file_counter.times do
file_name, file_size, tail = not_parsed.split(':', 3)
files[file_name] = File.parse tail[0, file_size.to_i]
not_parsed = tail[file_size.to_i, not_parsed.size]
end
[files, not_parsed]
end
end
class Directory
def initialize(files = {}, directories = {})
@folder = {files: files, directories: directories}
end
def add_file(name, file = File.new)
@folder[:files][name] = file
end
def add_directory(name, directory = Directory.new)
@folder[:directories][name] = directory
end
def files
@folder[:files]
end
def directories
@folder[:directories]
end
def [](name)
directories.fetch(name, files[name])
end
def serialize
serialized = ''
serialized.concat(files.size.to_s).concat(':')
files.each_pair do |key, value|
serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized.concat(directories.size.to_s).concat(':')
directories.each_pair do |key, value|
serialized.concat "#{key}:#{value.serialize.length}:#{value.serialize}"
end
serialized
end
def self.parse(string_data)
- folders, (files, not_parsed) ={}, File.multi_parse(string_data)
+ folders, (files, not_parsed) ={}, File.parse_multiple_files(string_data)
folder_counter = not_parsed.partition(':').first.to_i
not_parsed = not_parsed.partition(':').last
folder_counter.times do
folder_name, folder_size, tail = not_parsed.split(':', 3)
folders[folder_name] = Directory.parse(tail[0, folder_size.to_i])
not_parsed = tail[folder_size.to_i, not_parsed.size]
end
Directory.new(files, folders)
end
end
end