patternrubyMinor
Calculating change based on input
Viewed 0 times
inputcalculatingchangebased
Problem
I decided to make a program that calculates change, based on an input. My code is extremely long, and I would like to know how I can fix this.
Examples
make_change(42) should result in
=> {:Q => 1, :D => 1, :N => 1, :P => 2
make_change(91) should result in
=> {:H => 1, :Q => 1, :D => 1, :N => 1, :P => 1
def make_change(amount)
values = []
coins = []
hash = {}
if amount >= 50
coins.push(:H)
values.push(amount / 50)
amount = amount % 50
if amount % 50 >= 25
coins.push(:Q)
values.push(amount / 25)
amount = amount % 25
if amount % 25 >= 10
coins.push(:D)
values.push(amount / 10)
amount = amount % 10
if amount % 10 >= 5
coins.push(:N)
values.push(amount / 5)
amount = amount % 5
if amount % 5 >= 1
coins.push(:P)
values.push(amount / 1)
end
end
end
end
elsif amount >= 25
coins.push(:Q)
values.push(amount / 25)
amount = amount % 25
if amount % 25 >= 10
coins.push(:D)
values.push(amount/10)
amount = amount % 10
if amount % 10 >= 5
coins.push(:N)
values.push(amount/5)
amount = amount % 5
if amount % 5 >= 1
coins.push(:P)
values.push(amount/1)
end
end
end
elsif amount >= 10
coins.push(:D)
values.push(amount / 10)
amount = amount % 10
if amount % 10 >= 5
coins.push(:N)
values.push(amount / 5)
amount = amount % 5
if amount % 5 >= 1
coins.push(:P)
values.push(amount / 1)
end
end
elsif amount >= 5
coins.push(:N)
values.push(amount / 5)
amount = amount % 5
if amount % 5 >= 1
coins.push(:P)
values.push(amount / 1)
end
elsif amount >= 1
coins.push(:P)
values.push(amount / 1)
else
coins = []
values = []
end
Hash[coins.zip(values)]
endExamples
make_change(42) should result in
=> {:Q => 1, :D => 1, :N => 1, :P => 2
make_change(91) should result in
=> {:H => 1, :Q => 1, :D => 1, :N => 1, :P => 1
Solution
Here's one way, that uses the method Fixnum#divmod to advantage:
COINS = [["H", 50], ["Q", 25], ["D", 10], ["N", 5], ["P", 1]]
def change(amount)
raise ArgumentError, 'Only non-negative integers permitted' unless
amount.is_a?(Fixnum) && amount >= 0
return [] if amount.zero?
COINS.map do |label, value|
nbr, amount = amount.divmod(value)
[nbr, label]
end
end
change(260) #=> [[5, "H"], [0, "Q"], [1, "D"], [0, "N"], [0, "P"]]
change(95) #=> [[1, "H"], [1, "Q"], [2, "D"], [0, "N"], [0, "P"]]
change(100) #=> [[2, "H"], [0, "Q"], [0, "D"], [0, "N"], [0, "P"]]
change(80) #=> [[1, "H"], [1, "Q"], [0, "D"], [1, "N"], [0, "P"]]
change(45) #=> [[0, "H"], [1, "Q"], [2, "D"], [0, "N"], [0, "P"]]
change(16) #=> [[0, "H"], [0, "Q"], [1, "D"], [1, "N"], [1, "P"]]
change(1) #=> [[0, "H"], [0, "Q"], [0, "D"], [0, "N"], [1, "P"]]
change(0) #=> []
change(-3) #=> ArgumentError: Only non-negative integers permitted...
change(1.2) #=> ArgumentError: Only non-negative integers permitted...
change('c') #=> ArgumentError: Only non-negative integers permitted...Code Snippets
COINS = [["H", 50], ["Q", 25], ["D", 10], ["N", 5], ["P", 1]]
def change(amount)
raise ArgumentError, 'Only non-negative integers permitted' unless
amount.is_a?(Fixnum) && amount >= 0
return [] if amount.zero?
COINS.map do |label, value|
nbr, amount = amount.divmod(value)
[nbr, label]
end
end
change(260) #=> [[5, "H"], [0, "Q"], [1, "D"], [0, "N"], [0, "P"]]
change(95) #=> [[1, "H"], [1, "Q"], [2, "D"], [0, "N"], [0, "P"]]
change(100) #=> [[2, "H"], [0, "Q"], [0, "D"], [0, "N"], [0, "P"]]
change(80) #=> [[1, "H"], [1, "Q"], [0, "D"], [1, "N"], [0, "P"]]
change(45) #=> [[0, "H"], [1, "Q"], [2, "D"], [0, "N"], [0, "P"]]
change(16) #=> [[0, "H"], [0, "Q"], [1, "D"], [1, "N"], [1, "P"]]
change(1) #=> [[0, "H"], [0, "Q"], [0, "D"], [0, "N"], [1, "P"]]
change(0) #=> []
change(-3) #=> ArgumentError: Only non-negative integers permitted...
change(1.2) #=> ArgumentError: Only non-negative integers permitted...
change('c') #=> ArgumentError: Only non-negative integers permitted...Context
StackExchange Code Review Q#69012, answer score: 2
Revisions (0)
No revisions yet.