HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

Calculating change based on input

Submitted by: @import:stackexchange-codereview··
0
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.

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)]
end


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

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.