Ошибка возникает при вызове [] в nil
объекте.
Когда вы передаете наименование, которого нет в переменной экземпляра @change
, результат @change.find { ... }
будет nil
,и вызов []
в объекте nil
вызовет ошибку NoMethodError.
Это случай, который вы не рассмотрели, и это можно решить с помощью next
в перечислителе each
:
coins.each do |coin|
current_denomination = @change.find { |x| x[:denomination] == coin }
next unless current_denomination
current_denomination[:amount] += 1
end
p pay([0.05, 0.05, 2.0, 100])
В случае, если нет изменений с той же монетой и номиналом, вы просто «переходите» к следующему элементу в монетах.
Обратите внимание, что текущая реализация @change
позволяет вам повторитьхэши в массиве, которые могут привести к ошибкам, если номинал отличается от первоначального значения количества.Вы можете просто использовать Hash для хранения как значения, так и суммы в качестве значения ключа:
p [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0].to_h { |a| [a, 5] }
# {0.01=>5, 0.02=>5, 0.05=>5, 0.1=>5, 0.2=>5, 0.5=>5, 1.0=>5, 2.0=>5}
Это Ruby 2.6 +.
В качестве незначительной настройки вашей реализации выможно переместить @change
в отдельный метод, который вы можете затем вызвать и использовать, вызвав для него tap
:
DENOMINATIONS = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0].freeze
HASH_KEYS = %i[denomination amount].freeze
def initial_coins
DENOMINATIONS.zip(Array.new(8, 5)).map { |coin| HASH_KEYS.zip(coin).to_h }
end
def pay(coins = [])
initial_coins.tap do |this|
coins.each do |coin|
current_denomination = this.find { |initial_coin| initial_coin[:denomination] == coin }
next unless current_denomination
current_denomination[:amount] += 1
end
end
end
pp pay([0.05, 0.05, 2.0, 100])
# [{:denomination=>0.01, :amount=>5},
# {:denomination=>0.02, :amount=>5},
# {:denomination=>0.05, :amount=>7},
# {:denomination=>0.1, :amount=>5},
# {:denomination=>0.2, :amount=>5},
# {:denomination=>0.5, :amount=>5},
# {:denomination=>1.0, :amount=>5},
# {:denomination=>2.0, :amount=>6}]