Решение на Осма задача от Десислава Цветкова

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

Към профила на Десислава Цветкова

Резултати

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

Код

class Spreadsheet
FORMAT = /[A-Z]+\d+/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
cells = row.strip.split(DELIMITER)
@sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
return cell if cell[0] != '='
calculate(CellHandler.make_formula(cell[1..-1], spread_sheet))
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula = formula_string
formula_string.gsub!(/^\s*[A-Z]+/) { |match| match.downcase }
formula.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
formula
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

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

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

Failures:

  1) Spreadsheet#[] raises an exception for unknown functions
     Failure/Error: expect { Spreadsheet.new('=FOO(42)  100')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Unknown function 'FOO'/, got #<Spreadsheet::Error: Unknown function 'foo'> with backtrace:
         # /tmp/d20160121-5693-p61s1p/solution.rb:149:in `method_error'
         # /tmp/d20160121-5693-p61s1p/solution.rb:141:in `handle_error'
         # /tmp/d20160121-5693-p61s1p/solution.rb:90:in `rescue in calculate'
         # /tmp/d20160121-5693-p61s1p/solution.rb:87:in `calculate'
         # /tmp/d20160121-5693-p61s1p/solution.rb:78:in `read_cell'
         # /tmp/d20160121-5693-p61s1p/solution.rb:32:in `[]'
         # /tmp/d20160121-5693-p61s1p/spec.rb:254:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-p61s1p/spec.rb:254:in `block (3 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)>'
     # /tmp/d20160121-5693-p61s1p/spec.rb:254:in `block (3 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) Spreadsheet#[] raises an exception for invalid expressions
     Failure/Error: expect { Spreadsheet.new('=FOO  100')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Invalid expression 'FOO'/ but nothing was raised
     # /tmp/d20160121-5693-p61s1p/spec.rb:266:in `block (3 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.03247 seconds
40 examples, 2 failures

Failed examples:

rspec /tmp/d20160121-5693-p61s1p/spec.rb:253 # Spreadsheet#[] raises an exception for unknown functions
rspec /tmp/d20160121-5693-p61s1p/spec.rb:265 # Spreadsheet#[] raises an exception for invalid expressions

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

Десислава обнови решението на 08.01.2016 15:39 (преди над 8 години)

+class Spreadsheet
+ FORMAT = /[A-Z]+\d+/
+ FIELD_SELECTOR = /(\w+\.?\w*|\=[A-Z]+(?:\(?(?:\w+\,\s*|\w+\.?\w*)*\)?)?)/
+ SIZE = 26
+ ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
+
+ class Error < RuntimeError
+ end
+
+ def initialize(cells = nil)
+ @calculator = SpreadsheetDSL.new
+ @sheet = []
+ return if cells.nil?
+ cells.strip.each_line { |row| @sheet << row.scan(FIELD_SELECTOR).flatten }
+ end
+
+ def empty?
+ @sheet.empty?
+ end
+
+ def cell_at(cell_index)
+ indices = CellHandler.make_check_indices(cell_index, @sheet)
+ @sheet[indices.first][indices.last]
+ end
+
+ def [](cell_index)
+ indices = CellHandler.make_check_indices(cell_index, @sheet)
+ @calculator.read_cell(@sheet[indices.first][indices.last], self)
+ end
+
+ def to_s
+ sheet = calculate_all
+ sheet.map do |row|
+ row.join("\t")
+ end.join("\n")
+ end
+
+private
+
+ def calculate_all()
+ sheet = []
+ @sheet.each_with_index do |row, i|
+ sheet << row.map.with_index do |col, j|
+ @calculator.read_cell(@sheet[i][j], self)
+ end
+ end
+ sheet
+ end
+
+ class SpreadsheetDSL
+
+ def add(argument_first, argument_second, *args)
+ args.reduce(0, :+) + argument_first + argument_second
+ end
+
+ def multiply(argument_first, argument_second, *args)
+ args.reduce(1, :*) * argument_first * argument_second
+ end
+
+ def subtract(argument_first, argument_second)
+ argument_first - argument_second
+ end
+
+ def divide(argument_first, argument_second)
+ argument_first.to_f / argument_second
+ end
+
+ def mod(argument_first, argument_second)
+ argument_first % argument_second
+ end
+
+ def read_cell(cell, spread_sheet)
+ return cell if /\w+/ =~ cell && cell[0] != '='
+ return format_result(cell.to_f) if cell[0] != '='
+ CellHandler.make_formula(cell, spread_sheet)
+ calculate(cell)
+ end
+
+ def format_result(result)
+ return result.to_i.to_s if result.round == result
+ format("%.2f", result)
+ end
+
+ def calculate(formula_string)
+ begin
+ result = instance_eval(formula_string)
+ rescue Exception => e
+ ErrorHandler.handle_error(e, formula_string)
+ else
+ format_result(result)
+ end
+ end
+ end
+
+ class CellHandler
+ class << self
+ def make_formula(formula_string, spread_sheet)
+ formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
+ formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
+ end
+
+ def make_check_indices(cell_index, sheet)
+ check_format(cell_index)
+ row = /\d+/.match(cell_index).to_a.first.to_i - 1
+ col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
+ check_boundaries(cell_index, row, col, sheet)
+ [row, col]
+ end
+
+ def calculate_column(col_string)
+ col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
+ sum + SIZE ** index * ORD[ch]
+ end
+ end
+
+ def check_format(cell_index)
+ formatted = cell_index.scan(FORMAT)
+ if formatted.size != 1
+ raise Error.new("Invalid cell index '#{cell_index}'")
+ elsif formatted.first != cell_index
+ raise Error.new("Invalid cell index '#{cell_index}'")
+ end
+ end
+
+ def check_boundaries(cell_index, row, col, sheet)
+ if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
+ raise Error.new("Cell '#{cell_index}' does not exist")
+ end
+ end
+ end
+ end
+
+ class ErrorHandler
+ class << self
+ def handle_error(e, formula_string)
+ case e
+ when NoMethodError then method_error(formula_string)
+ when SyntaxError then syntax_error(formula_string)
+ when ArgumentError then argument_error(formula_string, e)
+ end
+ end
+
+ def method_error(formula_string)
+ formula_string = formula_string[0...formula_string.index("(")]
+ raise Error.new("Unknown function '#{formula_string}'")
+ end
+
+ def syntax_error(formula_string)
+ raise Error.new("Invalid expression '#{formula_string.upcase}'")
+ end
+
+ def argument_error(formula_string, e)
+ at_least = e.message.include?('+') ? ' at least' : ''
+ formula_string = formula_string[0...formula_string.index("(")]
+ number = e.message.scan(/\d+/)
+ raise Error.new("Wrong number of arguments for " \
+ "'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
+ " got #{number[0]}")
+ end
+ end
+ end
+end

Десислава обнови решението на 08.01.2016 17:34 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
- FIELD_SELECTOR = /(\w+\.?\w*|\=[A-Z]+(?:\(?(?:\w+\,\s*|\w+\.?\w*)*\)?)?)/
+ DELIMITER = /(?<![\(\s\,])(\ {2,}|\t|^)(?![\)\s\,])/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
- cells.strip.each_line { |row| @sheet << row.scan(FIELD_SELECTOR).flatten }
+ cells.strip.each_line do |row|
+ @sheet << row.strip.gsub(DELIMITER, '|').split('|').reject(&:empty?)
+ end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
- return cell if /\w+/ =~ cell && cell[0] != '='
- return format_result(cell.to_f) if cell[0] != '='
+ return cell if ! cell[0].include?('=') && cell.to_f.to_s != cell
+ return format_result(cell.to_f) if ! cell[0].include?('=')
CellHandler.make_formula(cell, spread_sheet)
calculate(cell)
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 12:33 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
- DELIMITER = /(?<![\(\s\,])(\ {2,}|\t|^)(?![\)\s\,])/
+ #DELIMITER = /(?<![\(\s\,])(\ {2,}|\t|^)(?![\)\s\,])/
+ DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
+ attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
- @sheet << row.strip.gsub(DELIMITER, '|').split('|').reject(&:empty?)
+ @sheet << row.strip.split(DELIMITER)#.reject(&:empty?)
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
return cell if ! cell[0].include?('=') && cell.to_f.to_s != cell
return format_result(cell.to_f) if ! cell[0].include?('=')
CellHandler.make_formula(cell, spread_sheet)
calculate(cell)
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 14:41 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
- #DELIMITER = /(?<![\(\s\,])(\ {2,}|\t|^)(?![\)\s\,])/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
- @sheet << row.strip.split(DELIMITER)#.reject(&:empty?)
+ cells = row.strip.split(DELIMITER)
+ @sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
return cell if ! cell[0].include?('=') && cell.to_f.to_s != cell
return format_result(cell.to_f) if ! cell[0].include?('=')
CellHandler.make_formula(cell, spread_sheet)
calculate(cell)
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 14:49 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
cells = row.strip.split(DELIMITER)
@sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
- return cell if ! cell[0].include?('=') && cell.to_f.to_s != cell
- return format_result(cell.to_f) if ! cell[0].include?('=')
+ return cell if not cell.include?('=') && cell.to_f.to_s != cell
+ return format_result(cell.to_f) if not cell.include?('=')
CellHandler.make_formula(cell, spread_sheet)
calculate(cell)
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 17:14 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
cells = row.strip.split(DELIMITER)
@sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
- return cell if not cell.include?('=') && cell.to_f.to_s != cell
- return format_result(cell.to_f) if not cell.include?('=')
+ return cell if ! cell.include?('=') && cell.to_f.to_s != cell
+ return format_result(cell.to_f) if ! cell.include?('=')
CellHandler.make_formula(cell, spread_sheet)
- calculate(cell)
+ calculate(cell[1..-1])
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
- formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase[1..-1] }
+ formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase }
formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 17:55 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
cells = row.strip.split(DELIMITER)
@sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
- return cell if ! cell.include?('=') && cell.to_f.to_s != cell
- return format_result(cell.to_f) if ! cell.include?('=')
- CellHandler.make_formula(cell, spread_sheet)
- calculate(cell[1..-1])
+ return cell if cell[0] != '='
+ calculate(CellHandler.make_formula(cell[1..-1], spread_sheet))
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
- formula_string.gsub!(/\=[A-Z]+/) { |match| match.downcase }
- formula_string.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
+ formula = formula_string
+ formula_string.gsub!(/^\s*[A-Z]+/) { |match| match.downcase }
+ formula.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end

Десислава обнови решението на 09.01.2016 18:01 (преди над 8 години)

class Spreadsheet
FORMAT = /[A-Z]+\d+/
DELIMITER = /(?:\ {2,}|\t)/
SIZE = 26
ORD = ("A".."Z").to_a.zip((1..SIZE).to_a).to_h
class Error < RuntimeError
end
attr_reader :sheet
def initialize(cells = nil)
@calculator = SpreadsheetDSL.new
@sheet = []
return if cells.nil?
cells.strip.each_line do |row|
cells = row.strip.split(DELIMITER)
@sheet << cells if not cells.empty?
end
end
def empty?
@sheet.empty?
end
def cell_at(cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@sheet[indices.first][indices.last]
end
def [](cell_index)
indices = CellHandler.make_check_indices(cell_index, @sheet)
@calculator.read_cell(@sheet[indices.first][indices.last], self)
end
def to_s
sheet = calculate_all
sheet.map do |row|
row.join("\t")
end.join("\n")
end
private
def calculate_all()
sheet = []
@sheet.each_with_index do |row, i|
sheet << row.map.with_index do |col, j|
@calculator.read_cell(@sheet[i][j], self)
end
end
sheet
end
class SpreadsheetDSL
def add(argument_first, argument_second, *args)
args.reduce(0, :+) + argument_first + argument_second
end
def multiply(argument_first, argument_second, *args)
args.reduce(1, :*) * argument_first * argument_second
end
def subtract(argument_first, argument_second)
argument_first - argument_second
end
def divide(argument_first, argument_second)
argument_first.to_f / argument_second
end
def mod(argument_first, argument_second)
argument_first % argument_second
end
def read_cell(cell, spread_sheet)
return cell if cell[0] != '='
calculate(CellHandler.make_formula(cell[1..-1], spread_sheet))
end
def format_result(result)
return result.to_i.to_s if result.round == result
format("%.2f", result)
end
def calculate(formula_string)
begin
result = instance_eval(formula_string)
rescue Exception => e
ErrorHandler.handle_error(e, formula_string)
else
format_result(result)
end
end
end
class CellHandler
class << self
def make_formula(formula_string, spread_sheet)
formula = formula_string
formula_string.gsub!(/^\s*[A-Z]+/) { |match| match.downcase }
formula.gsub!(/[A-Z]+\d+/) { |match| spread_sheet[match] }
+ formula
end
def make_check_indices(cell_index, sheet)
check_format(cell_index)
row = /\d+/.match(cell_index).to_a.first.to_i - 1
col = calculate_column(/[A-Z]+/.match(cell_index).to_a.first) - 1
check_boundaries(cell_index, row, col, sheet)
[row, col]
end
def calculate_column(col_string)
col_string.reverse.each_char.with_index.reduce(0) do |sum, (ch, index) |
sum + SIZE ** index * ORD[ch]
end
end
def check_format(cell_index)
formatted = cell_index.scan(FORMAT)
if formatted.size != 1
raise Error.new("Invalid cell index '#{cell_index}'")
elsif formatted.first != cell_index
raise Error.new("Invalid cell index '#{cell_index}'")
end
end
def check_boundaries(cell_index, row, col, sheet)
if row < 0 || row >= sheet.size || col < 0 || col > sheet.first.size
raise Error.new("Cell '#{cell_index}' does not exist")
end
end
end
end
class ErrorHandler
class << self
def handle_error(e, formula_string)
case e
when NoMethodError then method_error(formula_string)
when SyntaxError then syntax_error(formula_string)
when ArgumentError then argument_error(formula_string, e)
end
end
def method_error(formula_string)
formula_string = formula_string[0...formula_string.index("(")]
raise Error.new("Unknown function '#{formula_string}'")
end
def syntax_error(formula_string)
raise Error.new("Invalid expression '#{formula_string.upcase}'")
end
def argument_error(formula_string, e)
at_least = e.message.include?('+') ? ' at least' : ''
formula_string = formula_string[0...formula_string.index("(")]
number = e.message.scan(/\d+/)
raise Error.new("Wrong number of arguments for " \
"'#{formula_string.upcase}': expected" + at_least + " #{number[1]}," \
" got #{number[0]}")
end
end
end
end