Решение на Осма задача от Любомир Папазов

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

Към профила на Любомир Папазов

Резултати

  • 3 точки от тестове
  • 0 бонус точки
  • 3 точки общо
  • 22 успешни тест(а)
  • 18 неуспешни тест(а)

Код

class Formulas
def self.formula_type(expression)
formula = expression.split('(')[0]
arguments = expression.split('(')[1].split(',').count
Formulas.public_send(formula.downcase , expression)
end
def self.add(arguments)
check_arguments_minimum('ADD', arguments, 2)
p "Pristigam s argumenti #{arguments}"
sum = 0
arguments.each do |number|
sum += Parser.text_to_number(number)
end
sum
end
def self.multiply(arguments)
check_arguments_minimum('MULTIPLY', arguments, 2)
product = 1
arguments.each do |number|
product *= Parser.text_to_number(number)
end
product
end
def self.subtract(arguments)
check_arguments_exact('SUBTRACT', arguments, 2)
arguments[1] - arguments[0]
end
def self.divide(arguments)
check_arguments_exact('DIVIDE', arguments, 2)
arguments[1] / arguments[0]
end
def self.mod(arguments)
check_arguments_exact('MOD', arguments, 2)
arguments[1] % arguments[0]
end
def self.check_arguments_minimum(function, arguments, expected_count)
if arguments.count < expected_count
raise Spreadsheet::Error, "Wrong number of arguments for '#{function}':
expected at least #{expected_count}, got #{arguments.count}"
end
end
def self.check_arguments_exact(function, arguments, expected_count)
if arguments.count != expected_count
raise Spreadsheet::Error, "Wrong number of arguments for
'#{function}': expected #{expected_count}, got #{arguments.count}"
end
end
end
class Parser
def self.text_to_number(number)
if number.to_i == number.to_f
number.to_i
else
number.to_f
end
end
def self.cell_value(index)
row_index = index.match(/\d+/).to_s.to_i
column_string = index.match(/[A-Z]+/).to_s
column_index = 0
column_string.reverse.split(//).each_with_index do |letter, index|
column_index += (letter.ord - 64) * (26 ** index)
end
[row_index, column_index]
end
end
class Spreadsheet
class Error < Exception
end
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
row, column = Parser.cell_value(index)[0], Parser.cell_value(index)[1]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
elsif row > @cells.count or column > @cells[0].count
raise Spreadsheet::Error, "Cell '#{index}' does not exist"
end
@cells[row - 1][column - 1].to_s
end
def [](index)
evaluate_cell(cell_at(index))
end
def evaluate_cell(content)
if content.start_with?('=')
evaluate_expression(content[1..content.length - 1].lstrip)
else
content
end
end
def evaluate_expression(expression)
if expression == expression.match(/\d+/).to_s
Parser.text_to_number(expression).to_s
elsif expression == expression.match(/[A-Z]+\d+/).to_s
cell_at(expression).to_s
else
calculate_formula(expression)
end
end
def calculate_formula(expression)
formula = expression[0..expression.length - 2].split('(')[0]
arguments = expression[0..expression.length - 2].split('(')[1].split(',')
real_values = arguments.map { |value| evaluate_expression(value.strip)}
begin
Formulas.public_send(formula.downcase , real_values).to_s
rescue NoMethodError
raise Spreadsheet::Error, "Unknown function '#{formula}'"
end
end
def to_s
result = ""
@cells.each do |row|
row.each do |cell|
result += evaluate_cell(cell.to_s).to_s + "\t"
end
result = result.strip + "\n"
end
result.strip
end
end

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

.........F....."Pristigam s argumenti [\"2\", \"2\"]"
."Pristigam s argumenti [\"2\", \"2\"]"
."Pristigam s argumenti [\"1\", \"2\", \"3\", \"4\", \"5\"]"
.F"Pristigam s argumenti [\"1\", \"42\", \"2\", \"10\"]"
."Pristigam s argumenti [\"3\", \"2\", \"5\"]"
..FFFFFFFFFFFFFFF..F

Failures:

  1) Spreadsheet#to_s returns the evaluated spreadsheet as a table
     Failure/Error: expect(sheet.to_s).to eq \
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1eawl1h/solution.rb:128:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `block in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `map'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:141:in `block (2 levels) in to_s'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:140:in `each'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:140:in `block in to_s'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:139:in `each'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:139:in `to_s'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:50: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 less than two arguments passed to ADD
     Failure/Error: expect { Spreadsheet.new('=ADD(1)')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Wrong number of arguments for 'ADD': expected at least 2, got 1/, got #<Spreadsheet::Error: Wrong number of arguments for 'ADD':
              expected at least 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:44:in `check_arguments_minimum'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:9:in `add'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `public_send'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:119:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:119: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-1eawl1h/spec.rb:119: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)>'

  3) Spreadsheet#[] raises an exception for less than two arguments to MULTIPLY
     Failure/Error: expect { Spreadsheet.new('=MULTIPLY(1)')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Wrong number of arguments for 'MULTIPLY': expected at least 2, got 1/, got #<Spreadsheet::Error: Wrong number of arguments for 'MULTIPLY':
              expected at least 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:44:in `check_arguments_minimum'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:19:in `multiply'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `public_send'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:149:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:149: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-1eawl1h/spec.rb:149: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)>'

  4) Spreadsheet#[] subtracts two numbers with SUBTRACT
     Failure/Error: expect(sheet['A1']).to eq('2')
     Spreadsheet::Error:
       Unknown function 'SUBTRACT'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:133:in `rescue in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:130:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:161: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)>'

  5) Spreadsheet#[] subtracts numbers via cell references
     Failure/Error: expect(sheet['D1']).to eq('4')
     Spreadsheet::Error:
       Unknown function 'SUBTRACT'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:133:in `rescue in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:130:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:167: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)>'

  6) Spreadsheet#[] raises an exception when SUBTRACT is called with a wrong number of arguments
     Failure/Error: expect { Spreadsheet.new('=SUBTRACT(1)')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Wrong number of arguments for 'SUBTRACT': expected 2, got 1/, got #<Spreadsheet::Error: Wrong number of arguments for
                  'SUBTRACT': expected 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:51:in `check_arguments_exact'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:28:in `subtract'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `public_send'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:171:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:171: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-1eawl1h/spec.rb:171: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)>'

  7) Spreadsheet#[] divides two numbers with DIVIDE
     Failure/Error: expect(sheet['A1']).to eq('42')
     Spreadsheet::Error:
       Unknown function 'DIVIDE'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:133:in `rescue in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:130:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:183: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)>'

  8) Spreadsheet#[] divides numbers via cell references
     Failure/Error: expect(sheet1['C1']).to eq('42')
     Spreadsheet::Error:
       Unknown function 'DIVIDE'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:133:in `rescue in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:130:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:190: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)>'

  9) Spreadsheet#[] raises an exception when DIVIDE is called with a wrong number of arguments
     Failure/Error: expect { Spreadsheet.new('=DIVIDE(1)')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Wrong number of arguments for 'DIVIDE': expected 2, got 1/, got #<Spreadsheet::Error: Wrong number of arguments for
                  'DIVIDE': expected 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:51:in `check_arguments_exact'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:33:in `divide'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `public_send'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:195:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:195: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-1eawl1h/spec.rb:195: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)>'

  10) Spreadsheet#[] calculates the modulo of two numbers with MOD
     Failure/Error: expect(Spreadsheet.new('=MOD(42, 5)')['A1']).to eq('2')
       
       expected: "2"
            got: "5"
       
       (compared using ==)
     # /tmp/d20160121-5693-1eawl1h/spec.rb:205: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)>'

  11) Spreadsheet#[] calculates the modulo of two numbers with MOD via cell references
     Failure/Error: expect(sheet1['C1']).to eq('4')
       
       expected: "4"
            got: "10"
       
       (compared using ==)
     # /tmp/d20160121-5693-1eawl1h/spec.rb:214: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)>'

  12) Spreadsheet#[] raises an exception when MOD is called with a wrong number of arguments
     Failure/Error: expect { Spreadsheet.new('=MOD(1)')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Wrong number of arguments for 'MOD': expected 2, got 1/, got #<Spreadsheet::Error: Wrong number of arguments for
                  'MOD': expected 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:51:in `check_arguments_exact'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:38:in `mod'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `public_send'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:131:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:219:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:219: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-1eawl1h/spec.rb:219: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)>'

  13) Spreadsheet#[] adds floating point numbers with ADD
     Failure/Error: expect(Spreadsheet.new('10  =ADD(A1, 1.1)')['B1']).to eq '11.10'
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1eawl1h/solution.rb:128:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `block in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `map'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:229: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)>'

  14) Spreadsheet#[] subtracts floating point numbers with SUBTRACT
     Failure/Error: expect(Spreadsheet.new('10  =SUBTRACT(A1, 1.1)')['B1']).to eq '8.90'
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1eawl1h/solution.rb:128:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `block in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `map'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:234: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)>'

  15) Spreadsheet#[] multiplies floating point numbers with MULTIPLY
     Failure/Error: expect(Spreadsheet.new('10  =MULTIPLY(A1, 1.1)')['B1']).to eq '11'
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1eawl1h/solution.rb:128:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `block in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `map'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:129:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:239: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)>'

  16) Spreadsheet#[] divides floating point numbers with DIVIDE
     Failure/Error: expect(Spreadsheet.new('10  =DIVIDE(A1, 4)')['B1']).to eq '2.50'
     Spreadsheet::Error:
       Unknown function 'DIVIDE'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:133:in `rescue in calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:130:in `calculate_formula'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
     # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
     # /tmp/d20160121-5693-1eawl1h/spec.rb:244: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)>'

  17) Spreadsheet#[] evaluates deeply-nested cell references
     Failure/Error: expect(Spreadsheet.new('10  =ADD(5, A1)  3  =DIVIDE(B1, C1)  =MOD(D1, 4)')['E1']).to eq '1'
       
       expected: "1"
            got: "4"
       
       (compared using ==)
     # /tmp/d20160121-5693-1eawl1h/spec.rb:250: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)>'

  18) 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'/, got #<NoMethodError: undefined method `split' for nil:NilClass> with backtrace:
         # /tmp/d20160121-5693-1eawl1h/solution.rb:128:in `calculate_formula'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:122:in `evaluate_expression'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:110:in `evaluate_cell'
         # /tmp/d20160121-5693-1eawl1h/solution.rb:105:in `[]'
         # /tmp/d20160121-5693-1eawl1h/spec.rb:266:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1eawl1h/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)>'
     # /tmp/d20160121-5693-1eawl1h/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.0329 seconds
40 examples, 18 failures

Failed examples:

rspec /tmp/d20160121-5693-1eawl1h/spec.rb:43 # Spreadsheet#to_s returns the evaluated spreadsheet as a table
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:118 # Spreadsheet#[] raises an exception for less than two arguments passed to ADD
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:148 # Spreadsheet#[] raises an exception for less than two arguments to MULTIPLY
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:158 # Spreadsheet#[] subtracts two numbers with SUBTRACT
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:164 # Spreadsheet#[] subtracts numbers via cell references
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:170 # Spreadsheet#[] raises an exception when SUBTRACT is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:180 # Spreadsheet#[] divides two numbers with DIVIDE
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:186 # Spreadsheet#[] divides numbers via cell references
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:194 # Spreadsheet#[] raises an exception when DIVIDE is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:204 # Spreadsheet#[] calculates the modulo of two numbers with MOD
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:210 # Spreadsheet#[] calculates the modulo of two numbers with MOD via cell references
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:218 # Spreadsheet#[] raises an exception when MOD is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:228 # Spreadsheet#[] adds floating point numbers with ADD
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:233 # Spreadsheet#[] subtracts floating point numbers with SUBTRACT
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:238 # Spreadsheet#[] multiplies floating point numbers with MULTIPLY
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:243 # Spreadsheet#[] divides floating point numbers with DIVIDE
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:249 # Spreadsheet#[] evaluates deeply-nested cell references
rspec /tmp/d20160121-5693-1eawl1h/spec.rb:265 # Spreadsheet#[] raises an exception for invalid expressions

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

Любомир обнови решението на 10.01.2016 21:13 (преди около 9 години)

+class Spreadsheet
+ class Error < Exception
+ end
+
+
+ def initialize(data = nil)
+ @cells = []
+ return if data == nil
+ rows = data.strip.split("\n").select {|row| !row.strip.empty?}
+ rows.each_with_index do |row, index|
+ @cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
+ end
+ end
+
+ def empty?
+ @cells.flatten.count == 0
+ end
+
+ def cell_at(index)
+ row, column = return_value(index)[1], return_value(index)[0]
+ if index != index.match(/[A-Z]+\d+/).to_s
+ raise Spreadsheet::Error, "Invalid cell index #{index}"
+ elsif row > @cells.count or column @cells[0].count
+ raise Spreadsheet::Error, "Cell #{index} does not exist"
+ end
+ return_value(index)
+ end
+
+ def return_value(index)
+ row_index = index.match(/\d+/).to_s.to_i
+ column_string = index.match(/[A-Z]+/).to_s
+ column_index = 0
+ column_string.reverse.split(//).each_with_index do |letter, index|
+ column_index += (letter.ord - 64) * (26 ** index)
+ end
+ [row_index, column_index]
+ end
+end

Любомир обнови решението на 10.01.2016 21:25 (преди около 9 години)

class Spreadsheet
class Error < Exception
end
-
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
row, column = return_value(index)[1], return_value(index)[0]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
elsif row > @cells.count or column @cells[0].count
raise Spreadsheet::Error, "Cell #{index} does not exist"
end
return_value(index)
end
def return_value(index)
row_index = index.match(/\d+/).to_s.to_i
column_string = index.match(/[A-Z]+/).to_s
column_index = 0
column_string.reverse.split(//).each_with_index do |letter, index|
column_index += (letter.ord - 64) * (26 ** index)
end
[row_index, column_index]
+ end
+
+ def to_s
+ result = ""
+ @cells.each do |row|
+ row.each do |cell|
+ result += cell.to_s + "\t"
+ end
+ result += "\n"
+ end
+ result.strip
end
end

Любомир обнови решението на 10.01.2016 21:27 (преди около 9 години)

class Spreadsheet
class Error < Exception
end
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
row, column = return_value(index)[1], return_value(index)[0]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
elsif row > @cells.count or column @cells[0].count
raise Spreadsheet::Error, "Cell #{index} does not exist"
end
return_value(index)
end
def return_value(index)
row_index = index.match(/\d+/).to_s.to_i
column_string = index.match(/[A-Z]+/).to_s
column_index = 0
column_string.reverse.split(//).each_with_index do |letter, index|
column_index += (letter.ord - 64) * (26 ** index)
end
[row_index, column_index]
end
def to_s
result = ""
@cells.each do |row|
row.each do |cell|
result += cell.to_s + "\t"
end
- result += "\n"
+ result = result.strip + "\n"
end
result.strip
end
end

Любомир обнови решението на 11.01.2016 02:55 (преди около 9 години)

+class Formulas
+ def self.formula_type(expression)
+ formula = expression.split('(')[0]
+ arguments = expression.split('(')[1].split(',').count
+ Formulas.public_send(formula.downcase , expression)
+ end
+
+ def self.add(arguments)
+ p "Pristigam s argumenti #{arguments}"
+ sum = 0
+ arguments.each do |number|
+ sum += Parser.text_to_number(number)
+ end
+ sum
+ end
+
+ def self.multiply(arguments)
+ p "Pristigam s argumenti #{arguments}"
+ product = 1
+ arguments.each do |number|
+ product *= Parser.text_to_number(number)
+ end
+ product
+ end
+
+ def self.subtract(arguments)
+ p "Pristigam s argumenti #{arguments}"
+ arguments[1] - arguments[0]
+ end
+
+ def self.divide(arguments)
+ p "Pristigam s argumenti #{arguments}"
+ arguments[1] / arguments[0]
+ end
+
+ def self.mod(arguments)
+ p "Pristigam s argumenti #{arguments}"
+ arguments[1] % arguments[0]
+ end
+end
+
+class Parser
+ def self.text_to_number(number)
+ if number.to_i == number.to_f
+ number.to_i
+ else
+ number.to_f
+ end
+ end
+
+ def self.cell_value(index)
+ row_index = index.match(/\d+/).to_s.to_i
+ column_string = index.match(/[A-Z]+/).to_s
+ column_index = 0
+ column_string.reverse.split(//).each_with_index do |letter, index|
+ column_index += (letter.ord - 64) * (26 ** index)
+ end
+ [row_index, column_index]
+ end
+end
+
class Spreadsheet
class Error < Exception
end
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
- row, column = return_value(index)[1], return_value(index)[0]
+ row, column = Parser.cell_value(index)[0], Parser.cell_value(index)[1]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
- elsif row > @cells.count or column @cells[0].count
+ elsif row > @cells.count or column > @cells[0].count
raise Spreadsheet::Error, "Cell #{index} does not exist"
end
- return_value(index)
+ @cells[row - 1][column - 1].to_s
end
- def return_value(index)
- row_index = index.match(/\d+/).to_s.to_i
- column_string = index.match(/[A-Z]+/).to_s
- column_index = 0
- column_string.reverse.split(//).each_with_index do |letter, index|
- column_index += (letter.ord - 64) * (26 ** index)
+ def [](index)
+ evaluate_cell(cell_at(index))
+ end
+
+ def evaluate_cell(content)
+ if content.start_with?('=')
+ evaluate_expression(content[1..content.length - 1].lstrip)
+ else
+ content
end
- [row_index, column_index]
end
+ def evaluate_expression(expression)
+ if expression == expression.match(/\d+/).to_s
+ Parser.text_to_number(expression)
+ elsif expression == expression.match(/[A-Z]+\d+/).to_s
+ cell_at(expression)
+ else
+ calculate_formula(expression)
+ end
+ end
+
+ def calculate_formula(expression)
+ formula = expression[0..expression.length - 2].split('(')[0]
+ arguments = expression[0..expression.length - 2].split('(')[1].split(',')
+ p arguments
+ real_values = arguments.map { |value| evaluate_expression(value.strip)}
+ p real_values
+ Formulas.public_send(formula.downcase , real_values).to_s
+ end
+
def to_s
result = ""
@cells.each do |row|
row.each do |cell|
- result += cell.to_s + "\t"
+ result += evaluate_cell(cell.to_s).to_s + "\t"
end
result = result.strip + "\n"
end
result.strip
end
end

Любомир обнови решението на 11.01.2016 12:42 (преди около 9 години)

class Formulas
def self.formula_type(expression)
formula = expression.split('(')[0]
arguments = expression.split('(')[1].split(',').count
Formulas.public_send(formula.downcase , expression)
end
def self.add(arguments)
p "Pristigam s argumenti #{arguments}"
sum = 0
arguments.each do |number|
sum += Parser.text_to_number(number)
end
sum
end
def self.multiply(arguments)
p "Pristigam s argumenti #{arguments}"
product = 1
arguments.each do |number|
product *= Parser.text_to_number(number)
end
product
end
def self.subtract(arguments)
p "Pristigam s argumenti #{arguments}"
arguments[1] - arguments[0]
end
def self.divide(arguments)
p "Pristigam s argumenti #{arguments}"
arguments[1] / arguments[0]
end
def self.mod(arguments)
p "Pristigam s argumenti #{arguments}"
arguments[1] % arguments[0]
end
end
class Parser
def self.text_to_number(number)
if number.to_i == number.to_f
number.to_i
else
number.to_f
end
end
def self.cell_value(index)
row_index = index.match(/\d+/).to_s.to_i
column_string = index.match(/[A-Z]+/).to_s
column_index = 0
column_string.reverse.split(//).each_with_index do |letter, index|
column_index += (letter.ord - 64) * (26 ** index)
end
[row_index, column_index]
end
end
class Spreadsheet
class Error < Exception
end
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
row, column = Parser.cell_value(index)[0], Parser.cell_value(index)[1]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
elsif row > @cells.count or column > @cells[0].count
raise Spreadsheet::Error, "Cell #{index} does not exist"
end
@cells[row - 1][column - 1].to_s
end
def [](index)
evaluate_cell(cell_at(index))
end
def evaluate_cell(content)
if content.start_with?('=')
evaluate_expression(content[1..content.length - 1].lstrip)
else
content
end
end
def evaluate_expression(expression)
if expression == expression.match(/\d+/).to_s
Parser.text_to_number(expression)
elsif expression == expression.match(/[A-Z]+\d+/).to_s
cell_at(expression)
else
calculate_formula(expression)
end
end
def calculate_formula(expression)
formula = expression[0..expression.length - 2].split('(')[0]
arguments = expression[0..expression.length - 2].split('(')[1].split(',')
- p arguments
real_values = arguments.map { |value| evaluate_expression(value.strip)}
- p real_values
- Formulas.public_send(formula.downcase , real_values).to_s
+ begin
+ Formulas.public_send(formula.downcase , real_values).to_s
+ rescue NoMethodError
+ raise Spreadsheet::Error, "Unknown function '#{formula}'"
+ end
end
def to_s
result = ""
@cells.each do |row|
row.each do |cell|
result += evaluate_cell(cell.to_s).to_s + "\t"
end
result = result.strip + "\n"
end
result.strip
end
end

Любомир обнови решението на 11.01.2016 13:20 (преди около 9 години)

class Formulas
def self.formula_type(expression)
formula = expression.split('(')[0]
arguments = expression.split('(')[1].split(',').count
Formulas.public_send(formula.downcase , expression)
end
def self.add(arguments)
+ check_arguments_minimum('ADD', arguments, 2)
p "Pristigam s argumenti #{arguments}"
sum = 0
arguments.each do |number|
sum += Parser.text_to_number(number)
end
sum
end
def self.multiply(arguments)
- p "Pristigam s argumenti #{arguments}"
+ check_arguments_minimum('MULTIPLY', arguments, 2)
product = 1
arguments.each do |number|
product *= Parser.text_to_number(number)
end
product
end
def self.subtract(arguments)
- p "Pristigam s argumenti #{arguments}"
+ check_arguments_exact('SUBTRACT', arguments, 2)
arguments[1] - arguments[0]
end
def self.divide(arguments)
- p "Pristigam s argumenti #{arguments}"
+ check_arguments_exact('DIVIDE', arguments, 2)
arguments[1] / arguments[0]
end
def self.mod(arguments)
- p "Pristigam s argumenti #{arguments}"
+ check_arguments_exact('MOD', arguments, 2)
arguments[1] % arguments[0]
end
+
+ def self.check_arguments_minimum(function, arguments, expected_count)
+ if arguments.count < expected_count
+ raise Spreadsheet::Error, "Wrong number of arguments for '#{function}':
+ expected at least #{expected_count}, got #{arguments.count}"
+ end
+ end
+
+ def self.check_arguments_exact(function, arguments, expected_count)
+ if arguments.count != expected_count
+ raise Spreadsheet::Error, "Wrong number of arguments for
+ '#{function}': expected #{expected_count}, got #{arguments.count}"
+ end
+ end
end
class Parser
def self.text_to_number(number)
if number.to_i == number.to_f
number.to_i
else
number.to_f
end
end
def self.cell_value(index)
row_index = index.match(/\d+/).to_s.to_i
column_string = index.match(/[A-Z]+/).to_s
column_index = 0
column_string.reverse.split(//).each_with_index do |letter, index|
column_index += (letter.ord - 64) * (26 ** index)
end
[row_index, column_index]
end
end
class Spreadsheet
class Error < Exception
end
def initialize(data = nil)
@cells = []
return if data == nil
rows = data.strip.split("\n").select {|row| !row.strip.empty?}
rows.each_with_index do |row, index|
@cells[index] = row.split(/(\t| +)/).select {|text| !text.strip.empty?}
end
end
def empty?
@cells.flatten.count == 0
end
def cell_at(index)
row, column = Parser.cell_value(index)[0], Parser.cell_value(index)[1]
if index != index.match(/[A-Z]+\d+/).to_s
raise Spreadsheet::Error, "Invalid cell index #{index}"
elsif row > @cells.count or column > @cells[0].count
- raise Spreadsheet::Error, "Cell #{index} does not exist"
+ raise Spreadsheet::Error, "Cell '#{index}' does not exist"
end
@cells[row - 1][column - 1].to_s
end
def [](index)
evaluate_cell(cell_at(index))
end
def evaluate_cell(content)
if content.start_with?('=')
evaluate_expression(content[1..content.length - 1].lstrip)
else
content
end
end
def evaluate_expression(expression)
if expression == expression.match(/\d+/).to_s
- Parser.text_to_number(expression)
+ Parser.text_to_number(expression).to_s
elsif expression == expression.match(/[A-Z]+\d+/).to_s
- cell_at(expression)
+ cell_at(expression).to_s
else
calculate_formula(expression)
end
end
def calculate_formula(expression)
formula = expression[0..expression.length - 2].split('(')[0]
arguments = expression[0..expression.length - 2].split('(')[1].split(',')
real_values = arguments.map { |value| evaluate_expression(value.strip)}
begin
Formulas.public_send(formula.downcase , real_values).to_s
rescue NoMethodError
raise Spreadsheet::Error, "Unknown function '#{formula}'"
end
end
def to_s
result = ""
@cells.each do |row|
row.each do |cell|
result += evaluate_cell(cell.to_s).to_s + "\t"
end
result = result.strip + "\n"
end
result.strip
end
end