Сбой метода, когда я следую руководству по стилю Ruby Rubocop и использую .zero?вместо == 0 - PullRequest
0 голосов
/ 12 июня 2018

TODO: вернуть массив целых чисел, 'Fizz', 'Buzz' или 'FizzBuzz'. Написать метод fizz_buzz, который принимает number в качестве аргумента, и вернуть массив number элементов от 1 доnumber, но заменяет некоторые из них согласно следующим правилам:

  • Если число делится на 3, то заменить его на 'Fizz'
  • Если числоделится на 5, затем заменить его на 'Buzz'
  • Если число делится на 3 и 5, то заменить его на 'FizzBuzz'

Если я буду следовать руководству по стилю rubocop и использовать .zero вместо == 0?мой метод не работает, и я не понимаю, почему

Мое решение с изменениями стилей теперь терпит неудачу

def fizz_buzz(number)
  fail ArgumentError, "#{number} is less than 1" if number < 1
  a = [number]
  while number > 1
    number = number - 1
    a.unshift(number)
    a.map! { |x| (x % 15).zero? ? 'FizzBuzz' : x }
    a.map! { |x| (x % 3).zero? ? 'Fizz' : x }
    a.map! { |x| (x % 5).zero? ? 'Buzz' : x }
  end
  a
end

  should return the array [ 1, 2, 'Fizz' ] for number 3 (FAILED - 1)
  should return the array [ 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7 ] for number 7 (FAILED - 2)
  should return an array with 'FizzBuzz' at the 15th element of the array (15 is divisible by both 3 and 5) (FAILED - 3)

Сбои:

  1) fizz_buzz should return the array [ 1, 2, 'Fizz' ] for number 3
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for "Fizz":String
 # ./lib/fizz_buzz.rb:12:in `block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'
 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:13:in `block (2 levels) in <top (required)>'

  2) fizz_buzz should return the array [ 1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7 ] for number 7
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for "Fizz":String
 # ./lib/fizz_buzz.rb:12:in `block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'
 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:17:in `block (2 levels) in <top (required)>'

  3) fizz_buzz should return an array with 'FizzBuzz' at the 15th element of the array (15 is divisible by both 3 and 5)
     Failure/Error: a.map! { |x| (x % 5).zero? ? 'Buzz' : x }

 NoMethodError:
   undefined method `zero?' for "Fizz":String
 # ./lib/fizz_buzz.rb:12:in `block in fizz_buzz'
 # ./lib/fizz_buzz.rb:12:in `map!'
 # ./lib/fizz_buzz.rb:12:in `fizz_buzz'
 # ./spec/fizz_buzz_spec.rb:21:in `block (2 levels) in <top (required)>'

Сбой моего рабочего решения со стилем

def fizz_buzz(number)
  fail ArgumentError, "#{number} is less than 1" if number < 1
  a = [number]
  while number > 1
    number = number - 1
    a.unshift(number)
    a.map! { |x| (x % 15) == 0 ? 'FizzBuzz' : x }
    a.map! { |x| (x % 3) == 0 ? 'Fizz' : x }
    a.map! { |x| (x % 5) == 0 ? 'Buzz' : x }
  end
  a
end

Данное решение

# def fizz_buzz(number)
#   fail ArgumentError, "#{number} should be greater than 1" if number < 1
#   (1..number).map do |i|
#     if (i % 3).zero? && (i % 5).zero?
#       'FizzBuzz'
#     elsif (i % 3).zero?
#       'Fizz'
#     elsif (i % 5).zero?
#       'Buzz'
#     else
#       i
#     end
#   end
# end

1 Ответ

0 голосов
/ 12 июня 2018

Теперь, когда мы видим сбойный код, вот почему он не работает:

У вас есть массив a, который, я полагаю, вы намеревались содержать в результатах.Вы добавляете к нему числа и исправляете числа, которые должны сказать «Fizz» или «Buzz» или «FizzBuzz».Это будет работать, но для одного критического сбоя: вы обрабатываете массив в каждой итерации цикла .Если бы вы просто исправили это один раз, перед тем, как вернуть, все было бы хорошо.Однако в этом случае происходит следующее (например, для входного значения 4):

  • Вы начинаете свой массив с 4
  • Вы запускаете исправления, но 4это хорошо, не требует исправления
  • Вы добавляете 3
  • Вы запускаете исправления;массив теперь ["Fizz", 4].Пока все хорошо.
  • Ты предпочитаешь 2;массив [2, "Fizz", 4]
  • Вы запускаете исправления.2 проходит без вмешательства, затем очередь "Fizz".
  • "Fizz" - это не число, поэтому вы не вызываете Number#%, оператор остатка, но String#%,оператор форматирования.В строке "Fizz" нет символов формата, поэтому оператор форматирования не делает ничего интересного и возвращает строку "Fizz".
  • Затем вы проверяете, равен ли он нулю.Когда вы пытаетесь "Fizz" == 0, это будет "Duh, no" и просто вернет false, поскольку все классы (начиная с BasicObject) определяют #==.Но "Fizz".zero? терпит неудачу, потому что в отличие от Number#zero?, String#zero? это не вещь.
...