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

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

Към профила на Христина Тодорова

Резултати

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

Код

module HelpFunctions
def digit?(char)
char <= '9' and char >= '0'
end
def letter?(char)
char <= 'Z' and char >= 'A'
end
def empty_row?(string)
(string.length - 1).times do |i|
if string[i] != " " then return false end
end
return true
end
def find_column(char)
column = 0
temporary = 'A'
until temporary == char
column += 1
temporary.next!
end
column
end
def get_row(string)
string.slice!(/[0-9]*/).to_i - 1
end
def get_column(string)
string.slice!(/[A-Z]*/)
end
def is_f?(number)
number.to_s.count('.') == 1
end
end
module HelpEvaluation
def adjust_formulas(string)
new_one = string
(string.length - 1).times do |i|
if new_one[i] == '='
new_one.sub!(new_one[i..new_one.index(')')],
new_one[i..new_one.index(')')].gsub!("\t", " "))
end
end
new_one
end
end
class Spreadsheet
include HelpFunctions
def initialize(argument = nil)
@sheet = Sheet.new
return unless argument != nil
make_table = argument.split("\n")
make_table.delete("")
make_table.each {|x| if ! empty_row?(x) then @sheet.push_row(x) end}
@to_s_state = ""
end
def empty?
@sheet.null?
end
def cell_at(cell_index)
check_the_index(cell_index)
column = get_column(cell_index)
row = get_row(cell_index)
real_column = find_column(column)
check_if_exists(row + 1, column,real_column)
@sheet.get_element(row, real_column)
end
def [](cell_index)
result_string = cell_at(cell_index)
@sheet.evaluate(result_string).to_s
end
def to_s
length = @sheet.table.length
length.times do |i|
@to_s_state << @sheet.print_row(i)
if i != length - 1 then @to_s_state << "\n" end
end
@to_s_state
end
private
def check_the_index(n)
invalid_index = Error.new("Invalid cell index '#{n}'")
raise invalid_index unless digit?(n[-1]) and letter?(n[0])
double_check(n, invalid_index)
n.length.times do |i|
raise invalid_index unless digit?(n[i]) or letter?(n[i])
end
end
def double_check(n, invalid_index)
(n.length - 1).times do |i|
if (digit?(n[i]) and letter?(n[i + 1]))
raise invalid_index
end
end
end
def check_if_exists(row, column, real_column)
invalid_index = Error.new("Cell '#{column}#{row}' does not exist")
if @sheet.table.size < row or @sheet.table.first.size < real_column
raise invalid_index
end
end
module HelpWithRounding
def calculate(string)
formula = Formula.new(string)
elements = formula.arguments
elements.map! { |x| x = evaluate(x) }
elements.map! { |x| x = x.round(2) }
result = elements.reduce(formula.get_operation)
round_number(result.to_s)
end
def round_number(number)
behind = number[/[.][0-9]*/]
if behind == ".0" or behind == ".00" or behind == nil
return number[/[0-9]*/]
end
if behind.length >= 4
round_tree_digits(number)
else
round_less_digits(number)
end
end
def round_less_digits(text)
front = text[/[0-9]*[.]/]
behind = text[/[.][0-9]*/]
front + behind[1..behind.length] + ("0" * (3 - behind.length))
end
def round_tree_digits(text)
front = text[/[0-9]*[.]/]
behind = text[/[.][0-9]*/]
if behind[3] >= '5'
return front + behind = behind[1..2].next!
else
front + behind[1..2]
end
end
end
class Sheet
include HelpFunctions
include HelpWithRounding
include HelpEvaluation
def initialize
@table = []
@current_result = ""
end
def null?
@table.length == 0
end
def push_row(array)
row = array.strip.gsub(/ */, "\t")
row = adjust_formulas(row)
elements = row.split("\t")
elements.delete("")
@table << elements
end
def get_element(row, column)
row = @table[row]
row[column]
end
def table
@table
end
def evaluate(string)
case
when (digit?(string[0]) or string[0] == '+' or string[0] == '-')
string.count('.') == 1 ? string.to_f : string.to_i
when string[0] == '='
calculate(string.delete("="))
else
text?(string)
end
end
def text?(string)
if digit?(string[-1])
column = get_column(string)
real_column = find_column(column)
row = get_row(string)
evaluate(get_element(row, real_column))
else
string
end
end
def print_row(index)
@current_result = ""
@table[index].each do |x|
digit?(x[-1]) ? @current_result << round_number(evaluate(x).to_s)
: @current_result << evaluate(x).to_s
if x != @table[index].last then @current_result << "\t" end
end
@current_result
end
end
begin
rescue Spreadsheet::Error => e
e.message
end
class Error < StandardError
end
class Formula
OPERATIONS = { "ADD" => '+' ,"MULTIPLY" => '*',
"SUBTRACT" => '-',"DIVIDE" => '/',"MOD" => '%' }
attr_accessor :arguments
def initialize(string)
@operation = ""
@arguments = []
check_for_unknown_function(string)
convert(string)
end
def get_operation
OPERATIONS[@operation].to_sym
end
def convert(string)
helper = string.split("(")
validate_expression(string[helper.first.length.. -1])
@operation = helper.first
helper.last.delete!(")")
remove_white_spaces(helper.last.split(","))
end
def remove_white_spaces(array)
array.each do |element|
while element.include? " "
element.sub!(/ */, "")
end
@arguments << element
end
validate_variables_first_check
validate_variables_second_check
end
def check_for_unknown_function(s)
unknown = Error.new("Unknown function '#{s.split("(").first}'")
if(OPERATIONS.has_key?(s.split("(").first) == false)
raise unknown
end
end
def validate_expression(s)
invalid_expression = Error.new("Invalid expression '#{s}'")
if s[-1] != (")") or s[0] != ("(")
raise invalid_expression
end
end
def validate_variables_first_check
variables = Error.new("Wrong number of arguments for #{@operation}
: expected at least 2, got #{@arguments.size}")
if @arguments.size < 2
raise variables
end
end
def validate_variables_second_check
variables = Error.new("Wrong number of arguments for #{@operation}
: expected 2, got #{@arguments.size}")
if (@operation == "SUBTRACT" or @operation == "DIVIDE" or
@operation == "MOD") and @arguments.size >= 3
raise variables
end
end
end
end

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

....F....F.....F..F...F..F..F..F....FFFF

Failures:

  1) Spreadsheet#to_s returns blank tables as blank strings
     Failure/Error: expect(Spreadsheet.new.to_s).to eq ''
       
       expected: ""
            got: nil
       
       (compared using ==)
     # /tmp/d20160121-5693-1ugfopt/spec.rb:24: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#to_s returns the evaluated spreadsheet as a table
     Failure/Error: expect(sheet.to_s).to eq \
       
       expected: "foo\t10\t2.1\t15\nbar\t11\t2.2\t5\nbaz\t12\t2.3\t27.60"
            got: "foo\t10\t2.10\t15\nbar\t11\t2.20\t5\nbaz\t12\t2.30\t27.60"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -foo	10	2.1	15
       -bar	11	2.2	5
       -baz	12	2.3	27.60
       +foo	10	2.10	15
       +bar	11	2.20	5
       +baz	12	2.30	27.60
     # /tmp/d20160121-5693-1ugfopt/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)>'

  3) Spreadsheet#[] returns the calculated value of formulae cells
     Failure/Error: sheet = Spreadsheet.new "foo\tADD(2, 2)\t=ADD(2, 2)"
     TypeError:
       no implicit conversion of nil into String
     # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
     # /tmp/d20160121-5693-1ugfopt/spec.rb:99:in `new'
     # /tmp/d20160121-5693-1ugfopt/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)>'

  4) 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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:119:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:119:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  5) 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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:149:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:149:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:171:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:171:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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#[] 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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:195:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:195:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  8) 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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:219:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:219:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  9) 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'
     TypeError:
       no implicit conversion of nil into String
     # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
     # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
     # /tmp/d20160121-5693-1ugfopt/spec.rb:250:in `new'
     # /tmp/d20160121-5693-1ugfopt/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)>'

  10) 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 #<TypeError: no implicit conversion of nil into String> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `sub!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:254:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:254:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  11) 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 `[]' for nil:NilClass> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:193:in `get_element'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:216:in `text?'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:207:in `evaluate'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:130:in `block in calculate'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:130:in `map!'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:130:in `calculate'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:205:in `evaluate'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:87:in `[]'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:260:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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)>'

  12) 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 #<ArgumentError: bad value for range> with backtrace:
         # /tmp/d20160121-5693-1ugfopt/solution.rb:48:in `block in adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `times'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:46:in `adjust_formulas'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:185:in `push_row'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `block in initialize'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `each'
         # /tmp/d20160121-5693-1ugfopt/solution.rb:68:in `initialize'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:266:in `new'
         # /tmp/d20160121-5693-1ugfopt/spec.rb:266:in `block (4 levels) in <top (required)>'
         # /tmp/d20160121-5693-1ugfopt/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-1ugfopt/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.042 seconds
40 examples, 12 failures

Failed examples:

rspec /tmp/d20160121-5693-1ugfopt/spec.rb:23 # Spreadsheet#to_s returns blank tables as blank strings
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:43 # Spreadsheet#to_s returns the evaluated spreadsheet as a table
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:98 # Spreadsheet#[] returns the calculated value of formulae cells
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:118 # Spreadsheet#[] raises an exception for less than two arguments passed to ADD
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:148 # Spreadsheet#[] raises an exception for less than two arguments to MULTIPLY
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:170 # Spreadsheet#[] raises an exception when SUBTRACT is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:194 # Spreadsheet#[] raises an exception when DIVIDE is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:218 # Spreadsheet#[] raises an exception when MOD is called with a wrong number of arguments
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:249 # Spreadsheet#[] evaluates deeply-nested cell references
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:253 # Spreadsheet#[] raises an exception for unknown functions
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:259 # Spreadsheet#[] raises an exception for missing cells passed as function arguments
rspec /tmp/d20160121-5693-1ugfopt/spec.rb:265 # Spreadsheet#[] raises an exception for invalid expressions

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

Христина обнови решението на 11.01.2016 15:01 (преди над 8 години)

+module HelpFunctions
+
+ def digit?(char)
+ char <= '9' and char >= '0'
+ end
+
+ def letter?(char)
+ char <= 'Z' and char >= 'A'
+ end
+
+ def empty_row?(string)
+ (string.length - 1).times do |i|
+ if string[i] != " " then return false end
+ end
+ return true
+ end
+
+ def find_column(char)
+ column = 0
+ temporary = 'A'
+ until temporary == char
+ column += 1
+ temporary.next!
+ end
+ column
+ end
+
+ def get_row(string)
+ string.slice!(/[0-9]*/).to_i - 1
+ end
+
+ def get_column(string)
+ string.slice!(/[A-Z]*/)
+ end
+
+ def is_f?(number)
+ number.to_s.count('.') == 1
+ end
+
+ def evaluate(string)
+ case
+ when (digit?(string[0]) or string[0] == '+' or string[0] == '-')
+ string.count('.') == 1 ? string.to_f : string.to_i
+ when string[0] == '='
+ calculate(string.delete("="))
+ else
+ evaluate(get_element(get_row(string) - 1,
+ find_column(get_column(string))))
+ end
+ end
+
+end
+
+module HelpWithRounding
+
+ def round_number(number)
+ behind = number[/[.][0-9]*/]
+ if behind == ".0" or behind == ".00" or behind == nil
+ return number[/[0-9]*[.]*/].delete(".")
+ end
+ if behind.length >= 4
+ round_tree_digits(number)
+ else
+ round_less_digits(number)
+ end
+ end
+
+ def round_less_digits(text)
+ front = text[/[0-9]*[.]/]
+ behind = text[/[.][0-9]*/]
+
+ front + behind[1..behind.length] + ("0" * (3 - behind.length))
+ end
+
+ def round_tree_digits(text)
+ front = text[/[0-9]*[.]/]
+ behind = text[/[.][0-9]*/]
+ if behind[3] >= '5'
+ return front + behind = behind[1..2].next!
+ else
+ front + behind[1..2]
+ end
+ end
+
+end
+
+
+class Spreadsheet
+
+ include HelpFunctions
+
+ def initialize(argument = nil)
+ @sheet = Sheet.new
+ return unless argument != nil
+ make_table = argument.split("\n")
+ make_table.delete("")
+ make_table.each {|x| if ! empty_row?(x) then @sheet.push_row(x) end}
+ @to_s_state = ""
+ end
+
+ def empty?
+ @sheet.null?
+ end
+
+ def cell_at(cell_index)
+ check_the_index(cell_index)
+ column = get_column(cell_index)
+ row = get_row(cell_index)
+ real_column = find_column(column)
+ check_if_exists(row + 1, column,real_column)
+ @sheet.get_element(row, real_column)
+ end
+
+ def [](cell_index)
+ result_string = cell_at(cell_index)
+ @sheet.evaluate(result_string).to_s
+ end
+
+ def to_s
+ length = @sheet.table.length
+ length.times do |i|
+ @to_s_state << @sheet.print_row(i)
+ if i != length - 1 then @to_s_state << "\n" end
+ end
+ @to_s_state
+ end
+
+ private
+
+ def check_the_index(n)
+ invalid_index = Error.new("Invalid cell index '#{n}'")
+ raise invalid_index unless digit?(n[-1]) and letter?(n[0])
+ double_check(n, invalid_index)
+ n.length.times do |i|
+ raise invalid_index unless digit?(n[i]) or letter?(n[i])
+ end
+ end
+
+ def double_check(n, invalid_index)
+ (n.length - 1).times do |i|
+ if (digit?(n[i]) and letter?(n[i + 1]))
+ raise invalid_index
+ end
+ end
+ end
+
+def check_if_exists(row, column, real_column)
+ invalid_index = Error.new("Cell '#{column}#{row}' does not exist")
+ if @sheet.table.size < row or @sheet.table.first.size < real_column
+ raise invalid_index
+ end
+ end
+
+ class Sheet
+
+ include HelpFunctions
+ include HelpWithRounding
+
+ def initialize
+ @table = []
+ @current_result = ""
+ end
+
+ def null?
+ @table.length == 0
+ end
+
+ def push_row(array)
+ row = array.strip.gsub(/ */, "\t")
+ row = adjust_formulas(row)
+ elements = row.split("\t")
+ elements.delete("")
+ @table << elements
+ end
+
+ def adjust_formulas(string)
+ new_one = string
+ (string.length - 1).times do |i|
+ if new_one[i] == '='
+ new_one.sub!(new_one[i..new_one.index(')')],
+ new_one[i..new_one.index(')')].gsub!("\t", " "))
+ end
+ end
+ new_one
+ end
+
+ def get_element(row, column)
+ row = @table[row]
+ row[column]
+ end
+
+ def table
+ @table
+ end
+
+ def calculate(string)
+ formula = Formula.new(string)
+ elements = formula.arguments
+ elements.map! { |x| x = evaluate(x) }
+ elements.map! { |x| x = x.round(2) }
+ elements.reduce(formula.get_operation)
+ end
+
+ def print_row(index)
+ @current_result = ""
+ @table[index].each do |x|
+ digit?(x[-1]) ? @current_result << round_number(evaluate(x).to_s)
+ : @current_result << evaluate(x).to_s
+ if x != @table[index].last then @current_result << "\t" end
+ end
+ @current_result
+ end
+
+ end
+
+ begin
+ rescue Spreadsheet::Error => e
+ e.message
+ end
+
+ class Error < StandardError
+ end
+
+ class Formula
+
+ OPERATIONS = { "ADD" => '+' ,"MULTIPLY" => '*',
+ "SUBTRACT" => '-',"DIVIDE" => '/',"MOD" => '%' }
+
+ attr_accessor :arguments
+
+ def initialize(string)
+ @operation = ""
+ @arguments = []
+ check_for_unknown_function(string)
+ convert(string)
+ end
+
+ def get_operation
+ OPERATIONS[@operation].to_sym
+ end
+
+ def convert(string)
+ helper = string.split("(")
+ validate_expression(string[helper.first.length.. -1])
+ @operation = helper.first
+ helper.last.delete!(")")
+ remove_white_spaces(helper.last.split(","))
+ end
+
+ def remove_white_spaces(array)
+ array.each do |element|
+ while element.include? " "
+ element.sub!(/ */, "")
+ end
+ @arguments << element
+ end
+ validate_variables_first_check
+ validate_variables_second_check
+ end
+
+ def check_for_unknown_function(s)
+ unknown = Error.new("Unknown function '#{s.split("(").first}'")
+ if(OPERATIONS.has_key?(s.split("(").first) == false)
+ raise unknown
+ end
+ end
+
+ def validate_expression(s)
+ invalid_expression = Error.new("Invalid expression '#{s}'")
+ if s[-1] != (")") or s[0] != ("(")
+ raise invalid_expression
+ end
+ end
+
+ def validate_variables_first_check
+ variables = Error.new("Wrong number of arguments for #{@operation}
+ : expected at least 2, got #{@arguments.size}")
+ if @arguments.size < 2
+ raise variables
+ end
+ end
+
+ def validate_variables_second_check
+ variables = Error.new("Wrong number of arguments for #{@operation}
+ : expected 2, got #{@arguments.size}")
+ if (@operation == "SUBTRACT" or @operation == "DIVIDE" or
+ @operation == "MOD") and @arguments.size >= 3
+ raise variables
+ end
+ end
+
+ end
+
+end

Христина обнови решението на 11.01.2016 17:08 (преди над 8 години)

module HelpFunctions
def digit?(char)
char <= '9' and char >= '0'
end
def letter?(char)
char <= 'Z' and char >= 'A'
end
def empty_row?(string)
(string.length - 1).times do |i|
if string[i] != " " then return false end
end
return true
end
def find_column(char)
column = 0
temporary = 'A'
until temporary == char
column += 1
temporary.next!
end
column
end
def get_row(string)
string.slice!(/[0-9]*/).to_i - 1
end
def get_column(string)
string.slice!(/[A-Z]*/)
end
def is_f?(number)
number.to_s.count('.') == 1
end
- def evaluate(string)
- case
- when (digit?(string[0]) or string[0] == '+' or string[0] == '-')
- string.count('.') == 1 ? string.to_f : string.to_i
- when string[0] == '='
- calculate(string.delete("="))
- else
- evaluate(get_element(get_row(string) - 1,
- find_column(get_column(string))))
- end
- end
-
end
-module HelpWithRounding
+module HelpEvaluation
- def round_number(number)
- behind = number[/[.][0-9]*/]
- if behind == ".0" or behind == ".00" or behind == nil
- return number[/[0-9]*[.]*/].delete(".")
+ def adjust_formulas(string)
+ new_one = string
+ (string.length - 1).times do |i|
+ if new_one[i] == '='
+ new_one.sub!(new_one[i..new_one.index(')')],
+ new_one[i..new_one.index(')')].gsub!("\t", " "))
+ end
+ end
+ new_one
end
- if behind.length >= 4
- round_tree_digits(number)
- else
- round_less_digits(number)
- end
- end
- def round_less_digits(text)
- front = text[/[0-9]*[.]/]
- behind = text[/[.][0-9]*/]
-
- front + behind[1..behind.length] + ("0" * (3 - behind.length))
- end
-
- def round_tree_digits(text)
- front = text[/[0-9]*[.]/]
- behind = text[/[.][0-9]*/]
- if behind[3] >= '5'
- return front + behind = behind[1..2].next!
- else
- front + behind[1..2]
- end
- end
-
end
+
class Spreadsheet
include HelpFunctions
def initialize(argument = nil)
@sheet = Sheet.new
return unless argument != nil
make_table = argument.split("\n")
make_table.delete("")
make_table.each {|x| if ! empty_row?(x) then @sheet.push_row(x) end}
@to_s_state = ""
end
def empty?
@sheet.null?
end
def cell_at(cell_index)
check_the_index(cell_index)
column = get_column(cell_index)
row = get_row(cell_index)
real_column = find_column(column)
check_if_exists(row + 1, column,real_column)
@sheet.get_element(row, real_column)
end
def [](cell_index)
result_string = cell_at(cell_index)
@sheet.evaluate(result_string).to_s
end
def to_s
length = @sheet.table.length
length.times do |i|
@to_s_state << @sheet.print_row(i)
if i != length - 1 then @to_s_state << "\n" end
end
@to_s_state
end
private
def check_the_index(n)
invalid_index = Error.new("Invalid cell index '#{n}'")
raise invalid_index unless digit?(n[-1]) and letter?(n[0])
double_check(n, invalid_index)
n.length.times do |i|
raise invalid_index unless digit?(n[i]) or letter?(n[i])
end
end
def double_check(n, invalid_index)
(n.length - 1).times do |i|
if (digit?(n[i]) and letter?(n[i + 1]))
raise invalid_index
end
end
end
-def check_if_exists(row, column, real_column)
+ def check_if_exists(row, column, real_column)
invalid_index = Error.new("Cell '#{column}#{row}' does not exist")
if @sheet.table.size < row or @sheet.table.first.size < real_column
raise invalid_index
end
end
+ module HelpWithRounding
+
+ def calculate(string)
+ formula = Formula.new(string)
+ elements = formula.arguments
+ elements.map! { |x| x = evaluate(x) }
+ elements.map! { |x| x = x.round(2) }
+ result = elements.reduce(formula.get_operation)
+ round_number(result.to_s)
+ end
+
+ def round_number(number)
+ behind = number[/[.][0-9]*/]
+ if behind == ".0" or behind == ".00" or behind == nil
+ return number[/[0-9]*/]
+ end
+ if behind.length >= 4
+ round_tree_digits(number)
+ else
+ round_less_digits(number)
+ end
+ end
+
+ def round_less_digits(text)
+ front = text[/[0-9]*[.]/]
+ behind = text[/[.][0-9]*/]
+
+ front + behind[1..behind.length] + ("0" * (3 - behind.length))
+ end
+
+ def round_tree_digits(text)
+ front = text[/[0-9]*[.]/]
+ behind = text[/[.][0-9]*/]
+ if behind[3] >= '5'
+ return front + behind = behind[1..2].next!
+ else
+ front + behind[1..2]
+ end
+ end
+
+end
+
+
class Sheet
include HelpFunctions
include HelpWithRounding
+ include HelpEvaluation
def initialize
@table = []
@current_result = ""
end
def null?
@table.length == 0
end
def push_row(array)
row = array.strip.gsub(/ */, "\t")
row = adjust_formulas(row)
elements = row.split("\t")
elements.delete("")
@table << elements
end
- def adjust_formulas(string)
- new_one = string
- (string.length - 1).times do |i|
- if new_one[i] == '='
- new_one.sub!(new_one[i..new_one.index(')')],
- new_one[i..new_one.index(')')].gsub!("\t", " "))
- end
- end
- new_one
- end
-
def get_element(row, column)
row = @table[row]
row[column]
end
def table
@table
end
- def calculate(string)
- formula = Formula.new(string)
- elements = formula.arguments
- elements.map! { |x| x = evaluate(x) }
- elements.map! { |x| x = x.round(2) }
- elements.reduce(formula.get_operation)
+ def evaluate(string)
+ case
+ when (digit?(string[0]) or string[0] == '+' or string[0] == '-')
+ string.count('.') == 1 ? string.to_f : string.to_i
+ when string[0] == '='
+ calculate(string.delete("="))
+ else
+ text?(string)
+ end
+ end
+
+ def text?(string)
+ if digit?(string[-1])
+ column = get_column(string)
+ real_column = find_column(column)
+ row = get_row(string)
+ evaluate(get_element(row, real_column))
+ else
+ string
+ end
end
def print_row(index)
@current_result = ""
@table[index].each do |x|
digit?(x[-1]) ? @current_result << round_number(evaluate(x).to_s)
: @current_result << evaluate(x).to_s
if x != @table[index].last then @current_result << "\t" end
end
@current_result
end
end
begin
rescue Spreadsheet::Error => e
e.message
end
class Error < StandardError
end
class Formula
OPERATIONS = { "ADD" => '+' ,"MULTIPLY" => '*',
"SUBTRACT" => '-',"DIVIDE" => '/',"MOD" => '%' }
attr_accessor :arguments
def initialize(string)
@operation = ""
@arguments = []
check_for_unknown_function(string)
convert(string)
end
def get_operation
OPERATIONS[@operation].to_sym
end
def convert(string)
helper = string.split("(")
validate_expression(string[helper.first.length.. -1])
@operation = helper.first
helper.last.delete!(")")
remove_white_spaces(helper.last.split(","))
end
def remove_white_spaces(array)
array.each do |element|
while element.include? " "
element.sub!(/ */, "")
end
@arguments << element
end
validate_variables_first_check
validate_variables_second_check
end
def check_for_unknown_function(s)
unknown = Error.new("Unknown function '#{s.split("(").first}'")
if(OPERATIONS.has_key?(s.split("(").first) == false)
raise unknown
end
end
def validate_expression(s)
invalid_expression = Error.new("Invalid expression '#{s}'")
if s[-1] != (")") or s[0] != ("(")
raise invalid_expression
end
end
def validate_variables_first_check
variables = Error.new("Wrong number of arguments for #{@operation}
: expected at least 2, got #{@arguments.size}")
if @arguments.size < 2
raise variables
end
end
def validate_variables_second_check
variables = Error.new("Wrong number of arguments for #{@operation}
: expected 2, got #{@arguments.size}")
if (@operation == "SUBTRACT" or @operation == "DIVIDE" or
@operation == "MOD") and @arguments.size >= 3
raise variables
end
end
end
end