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

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

Към профила на Светлозар Тодоров

Резултати

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

Код

class String
def to_bool
downcase == 'true'
end
end
module RBFS
attr_accessor :data
attr_reader :data_type
class File
def self.parse(string_data)
parsed_data_type = string_data.split(':')[0]
parsed_data = string_data.split(':')[1]
data = string_to_data_type(parsed_data_type, parsed_data)
file = RBFS::File.new(data)
end
def initialize(*data)
@data = data[0]
end
def data
@data
end
def data=(new_data)
@data = new_data
end
def data_type
case @data
when Fixnum, Bignum, Float then :number
when NilClass then :nil
when String then :string
when Symbol then :symbol
when TrueClass, FalseClass then :boolean
end
end
def serialize
"#{data_type}:#{data}"
end
private
def string_to_data_type(data_type, data)
case data_type
when 'symbol' then data = data.to_sym
when 'number' then data = data.to_f
when 'boolean' then data = data.to_bool
end
data
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 = RBFS::Directory.new)
@directories[name] = directory
end
def [](name)
if @directories.keys.include? name
@directories[name]
elsif @files.keys.include? name
@files[name]
else
nil
end
end
def serialize
result = "#{@files.count}:"
@files.each do |key, value|
result << "#{key}:#{value.serialize.size}:#{value.serialize}"
end
result << "#{@directories.count}:"
@directories.each do |key, value|
result << "#{key}:#{value.serialize.size}:#{value.serialize}"
end
result
end
def self.parse(string_data)
# result_dir = RBFS::Directory.new
# info = string_data.split(':')
# # "2:README:19:string:Hello world!spec.rb:20:string:describe RBFS1:rbfs:4:0:0:"
# # "0:1:directory1:40:0:1:directory2:22:1:README:9:number:420:"
# # "0:0:"
# # "1:README:19:string:Hello world!"
# # file_size = string_data.split(':')[0]
# file_count = info[0] # => 2
# file_info = info.values_at(1..file_count.to_i*3+1) # =>
# file_count.to_i.times {
# file = RBFS::File.parse("#{file_info[3]}:#{file_info[4]}")
# result_dir.add_file(file_info, file)
# }
# result_dir
end
def files
@files
end
def directories
@directories
end
end
end

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

..........FFFF..........F..FF..F..F..F..F..F

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-redds4/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-redds4/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-redds4/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-redds4/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)>'

  5) RBFS File data type nil can be parsed
     Failure/Error: file = RBFS::File.parse('nil:')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:230: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)>'

  6) RBFS File data type string can be parsed
     Failure/Error: file = RBFS::File.parse('string:Hey there')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:248: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)>'

  7) RBFS File data type string can parse a string with colons
     Failure/Error: file = RBFS::File.parse('string:Hay :)')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:255: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)>'

  8) RBFS File data type symbol can be parsed
     Failure/Error: file = RBFS::File.parse('symbol:hello')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:274: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)>'

  9) RBFS File data type number can be parsed
     Failure/Error: file = RBFS::File.parse('number:1234')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:293: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)>'

  10) RBFS File data type float number can be parsed
     Failure/Error: file = RBFS::File.parse('number:3.14')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:312: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)>'

  11) RBFS File data type boolean true can be parsed
     Failure/Error: file = RBFS::File.parse('boolean:true')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:332:in `block (6 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)>'

  12) RBFS File data type boolean false can be parsed
     Failure/Error: file = RBFS::File.parse('boolean:false')
     NoMethodError:
       undefined method `string_to_data_type' for RBFS::File:Class
     # /tmp/d20141111-26053-redds4/solution.rb:15:in `parse'
     # /tmp/d20141111-26053-redds4/spec.rb:351:in `block (6 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.04165 seconds
44 examples, 12 failures

Failed examples:

rspec /tmp/d20141111-26053-redds4/spec.rb:100 # RBFS Directory serialization ::parse can parse empty directories
rspec /tmp/d20141111-26053-redds4/spec.rb:107 # RBFS Directory serialization ::parse can parse directories with files
rspec /tmp/d20141111-26053-redds4/spec.rb:116 # RBFS Directory serialization ::parse can parse directory trees without files
rspec /tmp/d20141111-26053-redds4/spec.rb:124 # RBFS Directory serialization ::parse can parse directories recursively
rspec /tmp/d20141111-26053-redds4/spec.rb:229 # RBFS File data type nil can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:247 # RBFS File data type string can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:254 # RBFS File data type string can parse a string with colons
rspec /tmp/d20141111-26053-redds4/spec.rb:273 # RBFS File data type symbol can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:292 # RBFS File data type number can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:311 # RBFS File data type float number can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:331 # RBFS File data type boolean true can be parsed
rspec /tmp/d20141111-26053-redds4/spec.rb:350 # RBFS File data type boolean false can be parsed

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

Светлозар обнови решението на 04.11.2014 02:18 (преди около 10 години)

+def converter(data_type, data)
+ case data_type
+ when 'symbol' then data = data.to_sym
+ when 'number' then data = data.to_numeric
+ when 'boolean' then data = data.to_bool
+ end
+ data
+end
+
+class String
+ def to_numeric
+ if self == self.to_i.to_s
+ self.to_i
+ else
+ self.to_f
+ end
+ end
+
+ def to_bool
+ self.downcase == 'true' ? true : false
+ end
+end
+
+module RBFS
+ attr_accessor :data
+ attr_reader :data_type
+
+ class File
+ def self.parse(string_data)
+ info = string_data.split(':')
+ data = converter(info[0], info[1])
+ file = RBFS::File.new(data)
+ end
+
+ def initialize(*data)
+ @data = data[0]
+ end
+
+ def data
+ @data
+ end
+
+ def data=(new_data)
+ @data = new_data
+ end
+
+ def data_type
+ case @data.class.to_s
+ when 'Fixnum', 'Bignum', 'Float' then :number
+ when 'NilClass' then :nil
+ when 'String' then :string
+ when 'Symbol' then :symbol
+ when 'TrueClass', 'FalseClass' then :boolean
+ end
+ end
+
+ def serialize
+ "#{data_type}:#{data}"
+ end
+ end
+
+ class Directory
+ attr_reader :files
+ attr_reader :directories
+
+ def initialize
+ @files = {}
+ @directories = {}
+ end
+
+ def add_file(name, file)
+ @files[name] = file unless name.include? ':'
+ end
+
+ def add_directory(name, *directory)
+ @directories[name] = directory[0] unless name.include? ':'
+ end
+
+ def [](name)
+ # code
+ end
+
+ def serialize
+ # code
+ end
+
+ def self.parse(string_data)
+ # code
+ end
+
+ def files
+ @files
+ end
+
+ def directories
+ @directories
+ end
+ end
+end

Привет!

Стигнах дотук днес. Дали ще може да почерпя малко конструктивна критика за следните неща и всичко останало?

  1. В метод data_type: мисля, че сме го споменавали и преди, но добра ли е идеята да се проверяват имената на класовете като стрингове? Или е по-хитро да се измисли нещо с is_a??
  2. Да мисля ли за по-подходящ начин за инициализация на файлове и директории? (така с взимане само на първия елемент от сплатнатия аргумент ми изглежда твърде лесно, чак граничещо с хак)
  3. Нещо в именуването, което се случва в self.parse не ми изглежда наред... Чудех се дали да не присвоя на две отделни променливи двата елемента на колекцията info, но така ми се получава повторение на string_data.split(':'). Да си мисля ли за нещо по-добро?
  4. Това в to_bool хубавият и предпочитан начин за използване на тернарен оператор ли е? (винаги тъй грешно го ползвам... :sweat:)

Благодаря предварително! :grin:

Привет :)

Може, разбира се:

  1. Не е добра идея :) Тук малко си се престарал. case може да проверява директно, без допълнителни методи, класа на някой обект:

     case object
       when String then ...
       when Symbol then ...
       ...
     end
    

    Това е следствие от факта, че case сравнява с ===.

  2. Изглежда ми странно. Като видя нещо такова и се чудя защо не се подава конкретното нещо, където се вика new. По-подходящият начин е просто да го направиш един аргумент на initialize и да викаш new с него там, където го използваш.

  3. Така е, трудно е да именуваш масив от две смислово отделени неща. Затова може да ги "разпакетираш" при присвояването - да станат две променливи, вместо info[0] и info[1].
  4. Не го нацели, съжалявам. :) Както би казал Станислав, това може да се напише и като downcase == 'true' ? true ? true ? true : false : false ? true : false : false ? true : false, но е по-добре да е просто downcase == 'true'. То самото връща булева стойност.

Малко други неща:

  • Когато ти потрябва помощен метод не го дефинирай глобално, а си го сложи като private в класа, в който го използваш. Името му също е малко странно.
  • to_numeric всъщност не ти е нужен
  • Няма нужда да проверяваш дали името съдържа :. Няма да ви подаваме невалидни аргументи, пък и ако трябваше да има тази проверка би било по-добре да се хвърли изключение, не да се "премълчава".

Светлозар обнови решението на 09.11.2014 17:51 (преди около 10 години)

-def converter(data_type, data)
- case data_type
- when 'symbol' then data = data.to_sym
- when 'number' then data = data.to_numeric
- when 'boolean' then data = data.to_bool
- end
- data
-end
-
class String
- def to_numeric
- if self == self.to_i.to_s
- self.to_i
- else
- self.to_f
- end
- end
-
def to_bool
- self.downcase == 'true' ? true : false
+ downcase == 'true'
end
end
module RBFS
attr_accessor :data
attr_reader :data_type
class File
def self.parse(string_data)
- info = string_data.split(':')
- data = converter(info[0], info[1])
+ # info = string_data.split(':')
+ parsed_data_type = string_data.split(':')[0]
+ parsed_data = string_data.split(':')[1]
+ data = string_to_data_type(parsed_data_type, parsed_data)
file = RBFS::File.new(data)
end
def initialize(*data)
@data = data[0]
end
def data
@data
end
def data=(new_data)
@data = new_data
end
def data_type
- case @data.class.to_s
- when 'Fixnum', 'Bignum', 'Float' then :number
- when 'NilClass' then :nil
- when 'String' then :string
- when 'Symbol' then :symbol
- when 'TrueClass', 'FalseClass' then :boolean
+ case @data
+ when Fixnum, Bignum, Float then :number
+ when NilClass then :nil
+ when String then :string
+ when Symbol then :symbol
+ when TrueClass, FalseClass then :boolean
end
end
def serialize
"#{data_type}:#{data}"
end
+
+ private
+
+ def string_to_data_type(data_type, data)
+ case data_type
+ when 'symbol' then data = data.to_sym
+ when 'number' then data = data.to_f
+ when 'boolean' then data = data.to_bool
+ end
+ data
+ end
end
class Directory
attr_reader :files
attr_reader :directories
def initialize
@files = {}
@directories = {}
end
def add_file(name, file)
- @files[name] = file unless name.include? ':'
+ @files[name] = file
end
def add_directory(name, *directory)
- @directories[name] = directory[0] unless name.include? ':'
+ @directories[name] = directory[0]
end
def [](name)
- # code
+ if @directories.keys.include? name
+ @directories[name]
+ elsif @files.keys.include? name
+ @files[name]
+ else
+ nil
+ end
end
def serialize
- # code
+ result = "#{@files.size}:"
+ @files.values.each do |value|
+ result << "#{@files.key(value)}:#{value.serialize.size}:#{value.serialize}"
+ end
+ @directories.values.each do |value|
+ result << "#{@directories.size}:#{@directories.key(value)}:"
+ end
+ result
end
def self.parse(string_data)
- # code
+ # 2:README:19:string:Hello world!spec.rb:20:string:describe RBFS1:rbfs:4:0:0:
+ # "0:1:directory1:40:0:1:directory2:22:1:README:9:number:420:"
end
def files
@files
end
def directories
@directories
end
end
end

Светлозар обнови решението на 09.11.2014 21:18 (преди около 10 години)

class String
def to_bool
downcase == 'true'
end
end
module RBFS
attr_accessor :data
attr_reader :data_type
class File
def self.parse(string_data)
- # info = string_data.split(':')
parsed_data_type = string_data.split(':')[0]
parsed_data = string_data.split(':')[1]
data = string_to_data_type(parsed_data_type, parsed_data)
file = RBFS::File.new(data)
end
def initialize(*data)
@data = data[0]
end
def data
@data
end
def data=(new_data)
@data = new_data
end
def data_type
case @data
when Fixnum, Bignum, Float then :number
when NilClass then :nil
when String then :string
when Symbol then :symbol
when TrueClass, FalseClass then :boolean
end
end
def serialize
"#{data_type}:#{data}"
end
private
def string_to_data_type(data_type, data)
case data_type
when 'symbol' then data = data.to_sym
when 'number' then data = data.to_f
when 'boolean' then data = data.to_bool
end
data
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)
- @directories[name] = directory[0]
+ def add_directory(name, directory = RBFS::Directory.new)
+ @directories[name] = directory
end
def [](name)
if @directories.keys.include? name
@directories[name]
elsif @files.keys.include? name
@files[name]
else
nil
end
end
def serialize
- result = "#{@files.size}:"
- @files.values.each do |value|
- result << "#{@files.key(value)}:#{value.serialize.size}:#{value.serialize}"
+ result = "#{@files.count}:"
+ @files.each do |key, value|
+ result << "#{key}:#{value.serialize.size}:#{value.serialize}"
end
- @directories.values.each do |value|
- result << "#{@directories.size}:#{@directories.key(value)}:"
+ result << "#{@directories.count}:"
+ @directories.each do |key, value|
+ result << "#{key}:#{value.serialize.size}:#{value.serialize}"
end
result
end
def self.parse(string_data)
- # 2:README:19:string:Hello world!spec.rb:20:string:describe RBFS1:rbfs:4:0:0:
- # "0:1:directory1:40:0:1:directory2:22:1:README:9:number:420:"
+ # result_dir = RBFS::Directory.new
+ # info = string_data.split(':')
+ # # "2:README:19:string:Hello world!spec.rb:20:string:describe RBFS1:rbfs:4:0:0:"
+ # # "0:1:directory1:40:0:1:directory2:22:1:README:9:number:420:"
+ # # "0:0:"
+ # # "1:README:19:string:Hello world!"
+ # # file_size = string_data.split(':')[0]
+ # file_count = info[0] # => 2
+ # file_info = info.values_at(1..file_count.to_i*3+1) # =>
+ # file_count.to_i.times {
+ # file = RBFS::File.parse("#{file_info[3]}:#{file_info[4]}")
+ # result_dir.add_file(file_info, file)
+ # }
+ # result_dir
end
def files
@files
end
def directories
@directories
end
end
end