Решение на Осма задача от Веселин Русинов

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

Към профила на Веселин Русинов

Резултати

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

Код

require 'pp'
class ColumnGenerator
def initialize(count)
@columns = []
@count = count
generate_columns('', @count)
end
def get_columns
@columns
end
private
def generate_letters(char, count)
@columns << (65..(90 - 26 + count)).map(&:chr).map { |x| x = "#{char}#{x}"}
@columns.flatten!
end
def generate_columns(char, count)
if (count >= 26)
generate_letters(char, 26)
generate_columns(@columns[@column_count += 1], count - 26)
else
generate_letters(char, count)
end
end
end
class Cell
attr_accessor :text_value, :real_value
def initialize(text_value, real_value)
@text_value, @real_value = text_value, real_value
end
def int?
@real_value.match(/^\d+$/) != nil
end
def get_int
@real_value.to_i
end
def to_s
mask = '%p'
if @real_value.is_a? Numeric
@real_value = @real_value.to_f
mask = if @real_value % 1 == 0 then '%d' else '%.2f' end
end
sprintf(mask, @real_value)
end
end
class Formula
attr_reader :result
def initialize(string, values)
@result = -1
check_brackets(string)
function_name = string[1..string.length].split(/\(/).first
eval "#{function_name.downcase}(#{values})"
end
def check_brackets(string)
open = string.index('(')
close = string.index(')')
if ! open || ! close || open > close
raise Spreadsheet::Error, "Invalid expression #{string}"
end
end
def get_messages(name, arguments)
@less = "Wrong number of arguments for 'FN': expected at least 2, got ARG"
@more = "Wrong number of arguments for 'FN': expected 2, got ARG"
less = @less.gsub("ARG", arguments.to_s).gsub("FN", name)
more = @more.gsub("ARG", arguments.to_s).gsub("FN", name)
[less, more]
end
def add(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("ADD", values.count)[0]
end
@result = values.inject(:+).to_f
end
def multiply(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("MULTIPLY", values.count)[0]
end
@result = values.inject(:*).to_f
end
def subtract(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[1]
end
@result = (values[0] - values[1]).to_f
end
def divide(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[1]
end
@result = (values[0] / values[1]).to_f
end
def mod(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("MOD", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("MOD", values.count)[1]
end
@result = (values[0] % values[1]).to_f
end
end
class Spreadsheet
class Error < StandardError
end
attr_accessor :table, :rows, :columns
def initialize(table = '')
@row_count, @column_count = 1, -1
@columns, @table = [], Hash.new
generator = ColumnGenerator.new((table.lines.first || '').split(' ').count)
@columns = generator.get_columns
@row_count , @column_count = 1, 0
populate_cells(table)
end
def populate_cells(table)
table.lines.each do |row|
@column_count = 0
row.split(' ').each do |cell|
add_cell(cell)
@column_count += 1
end
@row_count += 1
end
end
def check_table(value)
res = value
if value.match(/^\d+$/) == nil && cell_at(value)
res = @table[value].get_int
end
res.to_i
end
def add_cell(value)
real = value
if (value.start_with?("="))
split_values = value[/\((.*?)\)/, 1].split(',').map{ |s| check_table(s) }
real = Formula.new(value, split_values).result
end
@table["#{@columns[@column_count]}#{@row_count}"] = Cell.new(value, real)
end
def to_s
result, row = "", 1
print(result, row)
result
end
def print(result, row)
@table.each do |key, value|
if (/^*\d+$/.match(key).to_s.to_i == row)
result << value.to_s + "\t"
else
result << "\n#{value.to_s}\t"
row = /^*\d+$/.match(key).to_s.to_i
end
end
end
def cell_at(cell_index)
if ! @table.has_key? (cell_index)
raise Error, "Invalid cell index '#{cell_index}'"
else
@table[cell_index].text_value
end
end
def [](cell_index)
if ! @table.has_key? (cell_index)
raise Error, "Invalid cell index '#{cell_index}'"
else
@table[cell_index].real_value
end
end
end

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

.FFF.FFFFFFFF.FFFF.FFF.FFFFFFFFFFFFFFFFF

Failures:

  1) Spreadsheet#new creates a blank sheet when no arguments are passed
     Failure/Error: expect(Spreadsheet.new).to be_empty
     NoMethodError:
       undefined method `empty?' for #<Spreadsheet:0x007f9eedcadc60>
     # /tmp/d20160121-5693-1mpoek1/spec.rb:10: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#new creates a blank sheet when a blank string is passed
     Failure/Error: expect(Spreadsheet.new('')).to be_empty
     NoMethodError:
       undefined method `empty?' for #<Spreadsheet:0x007f9eedc24bb8>
     # /tmp/d20160121-5693-1mpoek1/spec.rb:14: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#new creates a non-empty sheet when a non-blank string is passed
     Failure/Error: expect(Spreadsheet.new('foo')).not_to be_empty
     NoMethodError:
       undefined method `empty?' for #<Spreadsheet:0x007f9eedbdbcd8>
     # /tmp/d20160121-5693-1mpoek1/spec.rb:18: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#to_s returns one-cell tables as a string
     Failure/Error: expect(Spreadsheet.new('foo').to_s).to eq 'foo'
       
       expected: "foo"
            got: "\"foo\"\t"
       
       (compared using ==)
     # /tmp/d20160121-5693-1mpoek1/spec.rb:28: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#to_s returns multi-cell, oneline tables as a string
     Failure/Error: expect(Spreadsheet.new("foo\tbar\tbaz").to_s).to eq "foo\tbar\tbaz"
       
       expected: "foo\tbar\tbaz"
            got: "\"foo\"\t\"bar\"\t\"baz\"\t"
       
       (compared using ==)
     # /tmp/d20160121-5693-1mpoek1/spec.rb:32: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#to_s returns multi-cell, multiline tables as a string
     Failure/Error: expect(Spreadsheet.new("foo\tbar\nbaz\tlarodi").to_s).to eq "foo\tbar\nbaz\tlarodi"
       
       expected: "foo\tbar\nbaz\tlarodi"
            got: "\"foo\"\t\"bar\"\t\n\"baz\"\t\"larodi\"\t"
       
       (compared using ==)
       
       Diff:
       @@ -1,3 +1,3 @@
       -foo	bar
       -baz	larodi
       +"foo"	"bar"	
       +"baz"	"larodi"	
     # /tmp/d20160121-5693-1mpoek1/spec.rb:36: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#to_s splits cells by two or more spaces
     Failure/Error: expect(Spreadsheet.new("foo  bar   42\nbaz    larodi  100").to_s).to eq "foo\tbar\t42\nbaz\tlarodi\t100"
       
       expected: "foo\tbar\t42\nbaz\tlarodi\t100"
            got: "\"foo\"\t\"bar\"\t\"42\"\t\n\"baz\"\t\"larodi\"\t\"100\"\t"
       
       (compared using ==)
       
       Diff:
       @@ -1,3 +1,3 @@
       -foo	bar	42
       -baz	larodi	100
       +"foo"	"bar"	"42"	
       +"baz"	"larodi"	"100"	
     # /tmp/d20160121-5693-1mpoek1/spec.rb:40: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#to_s returns the evaluated spreadsheet as a table
     Failure/Error: sheet = Spreadsheet.new <<-TABLE
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:44:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:44: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#cell_at raises and exception for non-existant cells
     Failure/Error: expect { Spreadsheet.new('foo')['B10'] }.to raise_error(Spreadsheet::Error, /Cell 'B10' does not exist/)
       expected Spreadsheet::Error with message matching /Cell 'B10' does not exist/, got #<Spreadsheet::Error: Invalid cell index 'B10'> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:200:in `[]'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:59:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:59: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-1mpoek1/spec.rb:59: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#cell_at returns the raw value of existing cells
     Failure/Error: sheet = Spreadsheet.new <<-TABLE
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:63:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:63: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#[] raises an exception for non-existant cells
     Failure/Error: expect { Spreadsheet.new()['A1'] }.to raise_error(Spreadsheet::Error, /Cell 'A1' does not exist/)
       expected Spreadsheet::Error with message matching /Cell 'A1' does not exist/, got #<Spreadsheet::Error: Invalid cell index 'A1'> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:200:in `[]'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:75:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:75: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-1mpoek1/spec.rb:75: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#[] returns the value of existing cells for complex cell indexes
     Failure/Error: sheet = Spreadsheet.new (["a#{"\tb" * 30}c"] * 20).join("\n")
     NoMethodError:
       undefined method `+' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:25:in `generate_columns'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:8:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:139:in `new'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:139:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:91:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:91: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#[] returns the calculated value of formulae cells
     Failure/Error: sheet = Spreadsheet.new "foo\tADD(2, 2)\t=ADD(2, 2)"
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:99:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:99: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#[] adds two numbers with ADD
     Failure/Error: sheet = Spreadsheet.new("=ADD(2, 2)")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:107:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:107: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#[] adds five numbers with ADD
     Failure/Error: sheet = Spreadsheet.new("=ADD(1, 2, 3, 4, 5)")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:113:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:113: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#[] adds numbers from cell references and as immediate arguments with ADD
     Failure/Error: sheet = Spreadsheet.new("42  =ADD(1, A1, 2, C1)  10")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:129:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:129: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#[] adds numbers only from cell references with ADD
     Failure/Error: sheet = Spreadsheet.new("2  3  5  =ADD(B1, A1, C1)  20")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:135:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:135: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#[] multiplies numbers with MULTIPLY
     Failure/Error: sheet1 = Spreadsheet.new("=MULTIPLY(1, 2, 3, 4, 5)")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:141:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:141: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)>'

  19) Spreadsheet#[] subtracts two numbers with SUBTRACT
     Failure/Error: sheet = Spreadsheet.new("=SUBTRACT(5, 3)  10")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:159:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:159: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)>'

  20) Spreadsheet#[] subtracts numbers via cell references
     Failure/Error: sheet = Spreadsheet.new("2  3  5  =SUBTRACT(C1, 1)  20")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:165:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:165: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)>'

  21) 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 at least 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # (eval):1:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `new'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:171:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:171:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/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-1mpoek1/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)>'

  22) Spreadsheet#[] divides two numbers with DIVIDE
     Failure/Error: sheet = Spreadsheet.new("=DIVIDE(84, 2)  10")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:181:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:181: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)>'

  23) Spreadsheet#[] divides numbers via cell references
     Failure/Error: sheet1 = Spreadsheet.new("2  84  =DIVIDE(B1, A1)  20")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:187:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:187: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)>'

  24) 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 at least 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # (eval):1:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `new'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:195:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:195:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/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-1mpoek1/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)>'

  25) Spreadsheet#[] calculates the modulo of two numbers with MOD
     Failure/Error: expect(Spreadsheet.new('=MOD(42, 5)')['A1']).to eq('2')
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:205:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  26) Spreadsheet#[] calculates the modulo of two numbers with MOD via cell references
     Failure/Error: sheet1 = Spreadsheet.new("10  84  =MOD(B1, A1)  20")
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:211:in `new'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:211: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)>'

  27) 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 at least 2, got 1> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # (eval):1:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `new'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:219:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:219:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/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-1mpoek1/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)>'

  28) 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-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:229:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  29) 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-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:234:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  30) 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-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:239:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  31) Spreadsheet#[] divides floating point numbers with DIVIDE
     Failure/Error: expect(Spreadsheet.new('10  =DIVIDE(A1, 4)')['B1']).to eq '2.50'
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:244:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  32) 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'
     NoMethodError:
       undefined method `split' for nil:NilClass
     # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
     # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
     # /tmp/d20160121-5693-1mpoek1/spec.rb:250:in `new'
     # /tmp/d20160121-5693-1mpoek1/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)>'

  33) 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 #<NoMethodError: undefined method `foo' for #<Formula:0x007f9eee6ff5d8 @result=-1>> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `eval'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `new'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:168:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:254:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:254:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/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-1mpoek1/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)>'

  34) Spreadsheet#[] raises an exception for missing cells passed as function arguments
     Failure/Error: expect { Spreadsheet.new('=ADD(1, B4)  100')['A1'] }.to raise_error(
       expected Spreadsheet::Error with message matching /Cell 'B4' does not exist/, got #<NoMethodError: undefined method `split' for nil:NilClass> with backtrace:
         # /tmp/d20160121-5693-1mpoek1/solution.rb:167:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:260:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:260:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:260: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-1mpoek1/spec.rb:260: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)>'

  35) 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-1mpoek1/solution.rb:167:in `add_cell'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:149:in `block (2 levels) in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:148:in `block in populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `each'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:146:in `populate_cells'
         # /tmp/d20160121-5693-1mpoek1/solution.rb:142:in `initialize'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:266:in `new'
         # /tmp/d20160121-5693-1mpoek1/spec.rb:266:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1mpoek1/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-1mpoek1/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.03709 seconds
40 examples, 35 failures

Failed examples:

rspec /tmp/d20160121-5693-1mpoek1/spec.rb:9 # Spreadsheet#new creates a blank sheet when no arguments are passed
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:13 # Spreadsheet#new creates a blank sheet when a blank string is passed
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:17 # Spreadsheet#new creates a non-empty sheet when a non-blank string is passed
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:27 # Spreadsheet#to_s returns one-cell tables as a string
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:31 # Spreadsheet#to_s returns multi-cell, oneline tables as a string
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:35 # Spreadsheet#to_s returns multi-cell, multiline tables as a string
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:39 # Spreadsheet#to_s splits cells by two or more spaces
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:43 # Spreadsheet#to_s returns the evaluated spreadsheet as a table
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:58 # Spreadsheet#cell_at raises and exception for non-existant cells
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:62 # Spreadsheet#cell_at returns the raw value of existing cells
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:74 # Spreadsheet#[] raises an exception for non-existant cells
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:90 # Spreadsheet#[] returns the value of existing cells for complex cell indexes
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:98 # Spreadsheet#[] returns the calculated value of formulae cells
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:106 # Spreadsheet#[] adds two numbers with ADD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:112 # Spreadsheet#[] adds five numbers with ADD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:128 # Spreadsheet#[] adds numbers from cell references and as immediate arguments with ADD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:134 # Spreadsheet#[] adds numbers only from cell references with ADD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:140 # Spreadsheet#[] multiplies numbers with MULTIPLY
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:158 # Spreadsheet#[] subtracts two numbers with SUBTRACT
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:164 # Spreadsheet#[] subtracts numbers via cell references
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:170 # Spreadsheet#[] raises an exception when SUBTRACT is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:180 # Spreadsheet#[] divides two numbers with DIVIDE
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:186 # Spreadsheet#[] divides numbers via cell references
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:194 # Spreadsheet#[] raises an exception when DIVIDE is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:204 # Spreadsheet#[] calculates the modulo of two numbers with MOD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:210 # Spreadsheet#[] calculates the modulo of two numbers with MOD via cell references
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:218 # Spreadsheet#[] raises an exception when MOD is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:228 # Spreadsheet#[] adds floating point numbers with ADD
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:233 # Spreadsheet#[] subtracts floating point numbers with SUBTRACT
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:238 # Spreadsheet#[] multiplies floating point numbers with MULTIPLY
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:243 # Spreadsheet#[] divides floating point numbers with DIVIDE
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:249 # Spreadsheet#[] evaluates deeply-nested cell references
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:253 # Spreadsheet#[] raises an exception for unknown functions
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:259 # Spreadsheet#[] raises an exception for missing cells passed as function arguments
rspec /tmp/d20160121-5693-1mpoek1/spec.rb:265 # Spreadsheet#[] raises an exception for invalid expressions

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

Веселин обнови решението на 11.01.2016 16:17 (преди над 9 години)

+require 'pp'
+
+class ColumnGenerator
+
+ def initialize(count)
+ @columns = []
+ @count = count
+ generate_columns('', @count)
+ end
+
+ def get_columns
+ @columns
+ end
+
+ private
+
+ def generate_letters(char, count)
+ @columns << (65..(90 - 26 + count)).map(&:chr).map { |x| x = "#{char}#{x}"}
+ @columns.flatten!
+ end
+
+ def generate_columns(char, count)
+ if (count >= 26)
+ generate_letters(char, 26)
+ generate_columns(@columns[@column_count += 1], count - 26)
+ else
+ generate_letters(char, count)
+ end
+ end
+
+end
+
+class Cell
+
+ attr_accessor :text_value, :real_value
+
+ def initialize(text_value, real_value)
+ @text_value, @real_value = text_value, real_value
+ end
+
+ def int?
+ @real_value.match(/^\d+$/) != nil
+ end
+
+ def get_int
+ @real_value.to_i
+ end
+
+ def to_s
+ @real_value
+ end
+
+end
+
+class Formula
+
+ attr_reader :result
+
+ def initialize(string, values)
+ @result = -1
+ check_brackets(string)
+ function_name = string[1..string.length].split(/\(/).first
+ eval "#{function_name.downcase}(#{values})"
+ end
+
+ def check_brackets(string)
+ open = string.index('(')
+ close = string.index(')')
+ if ! open || ! close || open > close
+ raise Spreadsheet::Error, "Invalid expression #{string}"
+ end
+ end
+
+ def get_messages(name, arguments)
+ @less = "Wrong number of arguments for 'FN': expected at least 2, got ARG"
+ @more = "Wrong number of arguments for 'FN': expected 2, got ARG"
+ less = @less.gsub("ARG", arguments.to_s).gsub("FN", name)
+ more = @more.gsub("ARG", arguments.to_s).gsub("FN", name)
+ [less, more]
+ end
+
+ def add(values)
+ if (values.count < 2)
+ raise Spreadsheet::Error, get_messages("ADD", values.count)[0]
+ end
+ @result = values.inject(:+)
+ end
+
+ def multiply(values)
+ if (values.count < 2)
+ raise Spreadsheet::Error, get_messages("MULTIPLY", values.count)[0]
+ end
+ @result = values.inject(:*)
+ end
+
+ def subtract(values)
+ if (values.count < 2)
+ raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[0]
+ elsif (values.count > 2)
+ raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[1]
+ end
+ @result = values[0] - values[1]
+ end
+
+ def divide(values)
+ if (values.count < 2)
+ raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[0]
+ elsif (values.count > 2)
+ raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[1]
+ end
+ @result = values[0] / values[1]
+ end
+
+ def mod(values)
+ if (values.count < 2)
+ raise Spreadsheet::Error, get_messages("MOD", values.count)[0]
+ elsif (values.count > 2)
+ raise Spreadsheet::Error, get_messages("MOD", values.count)[1]
+ end
+ @result = values[0] % values[1]
+ end
+end
+
+class Spreadsheet
+
+ class Error < StandardError
+ end
+
+ attr_accessor :table, :rows, :columns
+
+ def initialize(table = '')
+ @row_count, @column_count = 1, -1
+ @columns, @table = [], Hash.new
+ generator = ColumnGenerator.new((table.lines.first || '').split(' ').count)
+ @columns = generator.get_columns
+ @row_count , @column_count = 1, 0
+ populate_cells(table)
+ end
+
+ def populate_cells(table)
+ table.lines.each do |row|
+ @column_count = 0
+ row.split(' ').each do |cell|
+ add_cell(cell)
+ @column_count += 1
+ end
+ @row_count += 1
+ end
+ end
+
+ def check_table(value)
+ res = value
+ if value.match(/^\d+$/) == nil && cell_at(value)
+ res = @table[value].get_int
+ end
+ res.to_i
+ end
+
+ def add_cell(value)
+ real = value
+ if (value.start_with?("="))
+ split_values = value[/\((.*?)\)/, 1].split(',').map{ |s| check_table(s) }
+ real = Formula.new(value, split_values).result
+ end
+ @table["#{@columns[@column_count]}#{@row_count}"] = Cell.new(value, real)
+ end
+
+ def to_s
+ result, row = "", 1
+ print(result, row)
+ result
+ end
+
+ def print(result, row)
+ @table.each do |key, value|
+ if (/^*\d+$/.match(key).to_s.to_i == row)
+ result << value.real_value.to_s + "\t"
+ else
+ result << "\n#{value.real_value.to_s}\t"
+ row = /^*\d+$/.match(key).to_s.to_i
+ end
+ end
+ end
+
+ def cell_at(cell_index)
+ if ! @table.has_key? (cell_index)
+ raise Error, "Invalid cell index '#{cell_index}'"
+ else
+ @table[cell_index].text_value
+ end
+ end
+
+ def [](cell_index)
+ if ! @table.has_key? (cell_index)
+ raise Error, "Invalid cell index '#{cell_index}'"
+ else
+ @table[cell_index].real_value
+ end
+ end
+end

Веселин обнови решението на 11.01.2016 16:47 (преди над 9 години)

require 'pp'
class ColumnGenerator
def initialize(count)
@columns = []
@count = count
generate_columns('', @count)
end
def get_columns
@columns
end
private
def generate_letters(char, count)
@columns << (65..(90 - 26 + count)).map(&:chr).map { |x| x = "#{char}#{x}"}
@columns.flatten!
end
def generate_columns(char, count)
if (count >= 26)
generate_letters(char, 26)
generate_columns(@columns[@column_count += 1], count - 26)
else
generate_letters(char, count)
end
end
end
class Cell
attr_accessor :text_value, :real_value
def initialize(text_value, real_value)
@text_value, @real_value = text_value, real_value
end
def int?
@real_value.match(/^\d+$/) != nil
end
def get_int
@real_value.to_i
end
def to_s
- @real_value
+ mask = '%p'
+ if @real_value.is_a? Numeric
+ @real_value = @real_value.to_f
+ mask = if @real_value % 1 == 0 then '%d' else '%.2f' end
+ end
+ sprintf(mask, @real_value)
end
end
class Formula
attr_reader :result
def initialize(string, values)
@result = -1
check_brackets(string)
function_name = string[1..string.length].split(/\(/).first
eval "#{function_name.downcase}(#{values})"
end
def check_brackets(string)
open = string.index('(')
close = string.index(')')
if ! open || ! close || open > close
raise Spreadsheet::Error, "Invalid expression #{string}"
end
end
def get_messages(name, arguments)
@less = "Wrong number of arguments for 'FN': expected at least 2, got ARG"
@more = "Wrong number of arguments for 'FN': expected 2, got ARG"
less = @less.gsub("ARG", arguments.to_s).gsub("FN", name)
more = @more.gsub("ARG", arguments.to_s).gsub("FN", name)
[less, more]
end
def add(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("ADD", values.count)[0]
end
- @result = values.inject(:+)
+ @result = values.inject(:+).to_f
end
def multiply(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("MULTIPLY", values.count)[0]
end
- @result = values.inject(:*)
+ @result = values.inject(:*).to_f
end
def subtract(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("SUBTRACT", values.count)[1]
end
- @result = values[0] - values[1]
+ @result = (values[0] - values[1]).to_f
end
def divide(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("DIVIDE", values.count)[1]
end
- @result = values[0] / values[1]
+ @result = (values[0] / values[1]).to_f
end
def mod(values)
if (values.count < 2)
raise Spreadsheet::Error, get_messages("MOD", values.count)[0]
elsif (values.count > 2)
raise Spreadsheet::Error, get_messages("MOD", values.count)[1]
end
- @result = values[0] % values[1]
+ @result = (values[0] % values[1]).to_f
end
end
class Spreadsheet
class Error < StandardError
end
attr_accessor :table, :rows, :columns
def initialize(table = '')
@row_count, @column_count = 1, -1
@columns, @table = [], Hash.new
generator = ColumnGenerator.new((table.lines.first || '').split(' ').count)
@columns = generator.get_columns
@row_count , @column_count = 1, 0
populate_cells(table)
end
def populate_cells(table)
table.lines.each do |row|
@column_count = 0
row.split(' ').each do |cell|
add_cell(cell)
@column_count += 1
end
@row_count += 1
end
end
def check_table(value)
res = value
if value.match(/^\d+$/) == nil && cell_at(value)
res = @table[value].get_int
end
res.to_i
end
def add_cell(value)
real = value
if (value.start_with?("="))
split_values = value[/\((.*?)\)/, 1].split(',').map{ |s| check_table(s) }
real = Formula.new(value, split_values).result
end
@table["#{@columns[@column_count]}#{@row_count}"] = Cell.new(value, real)
end
def to_s
result, row = "", 1
print(result, row)
result
end
def print(result, row)
@table.each do |key, value|
if (/^*\d+$/.match(key).to_s.to_i == row)
- result << value.real_value.to_s + "\t"
+ result << value.to_s + "\t"
else
- result << "\n#{value.real_value.to_s}\t"
+ result << "\n#{value.to_s}\t"
row = /^*\d+$/.match(key).to_s.to_i
end
end
end
def cell_at(cell_index)
if ! @table.has_key? (cell_index)
raise Error, "Invalid cell index '#{cell_index}'"
else
@table[cell_index].text_value
end
end
def [](cell_index)
if ! @table.has_key? (cell_index)
raise Error, "Invalid cell index '#{cell_index}'"
else
@table[cell_index].real_value
end
end
end