Here's my memoized functional solution:
def make_change(amount, coins = [25, 10, 5, 1])
coins.sort! { |a, b| b <=> a }
# memoize solutions
optimal_change = Hash.new do |hash, key|
hash[key] = if key < coins.min
[]
elsif coins.include?(key)
[key]
else
coins.
# prune unhelpful coins
reject { |coin| coin > key }.
# prune coins that are factors of larger coins
inject([]) {|mem, var| mem.any? {|c| c%var == 0} ? mem : mem+
[var]}.
# recurse
map { |coin| [coin] + hash[key - coin] }.
# prune unhelpful solutions
reject { |change| change.sum != key }.
# pick the smallest, empty if none
min { |a, b| a.size <=> b.size } || []
end
end
optimal_change[amount]
end