Skip to content

Instantly share code, notes, and snippets.

@benneuman
Created February 21, 2014 04:31
Show Gist options
  • Save benneuman/9128796 to your computer and use it in GitHub Desktop.
Save benneuman/9128796 to your computer and use it in GitHub Desktop.
require 'rspec'
# input: integer (0-100)
# output: hash, e.g.
# 5 -> {quarters: 0, dimes: 0, nickels: 1, pennies: 0}
# 12 -> {quarters: 0, dimes: 1, nickels: 0, pennies: 2}
# describe "#make_change" do
# before {
# @change_maker = AmericanChangeMaker.new(ChangeMaker)
# }
# it "1 should return 1 penny" do
# expect(@change_maker.make_change(1)).to eq(quarters: 0, dimes: 0, nickels: 0, pennies: 1)
# end
# it "4 should return 4 pennies" do
# expect(@change_maker.make_change(4)).to eq(quarters: 0, dimes: 0, nickels: 0, pennies: 4)
# end
# it "5 should return 1 nickel" do
# expect(@change_maker.make_change(5)).to eq(quarters: 0, dimes: 0, nickels: 1, pennies: 0)
# end
# it "7 should return 1 nickel and 2 pennies" do
# expect(@change_maker.make_change(7)).to eq(quarters: 0, dimes: 0, nickels: 1, pennies: 2)
# end
# it "10 should return 1 dime" do
# expect(@change_maker.make_change(10)).to eq(quarters: 0, dimes: 1, nickels: 0, pennies: 0)
# end
# it "25 should return 1 quarter" do
# expect(@change_maker.make_change(25)).to eq(quarters: 1, dimes: 0, nickels: 0, pennies: 0)
# end
# end
# describe 'ChangeMaker' do
# before {
# @coin1 = Coin.new('onesie', 1)
# @coin2 = Coin.new('threesie', 3)
# @coin3 = Coin.new('eightsie', 8)
# @starting_cents = 39
# @change_maker = ChangeMaker.new(@starting_cents, [@coin1, @coin2, @coin3])
# }
# it "sorts coins descending by value" do
# @change_maker.coins.should == [@coin3, @coin2, @coin1]
# end
# describe "#coin_count" do
# it "records the name and count for each coin when make_change runs" do
# expect { @change_maker.make_change }
# .to change { @change_maker.coin_count }
# .from({})
# .to({
# eightsie: 4,
# threesie: 2,
# onesie: 1
# })
# end
# end
# describe "#coin_counter" do
# it "returns the remaining cents for largest coin" do
# expect(@change_maker.coin_counter(@starting_cents, @coin3))
# .to eq(@starting_cents % @coin3.value)
# end
# it "returns the remaining cents for second coin" do
# remaining_cents = @change_maker.remaining_change_count(@starting_cents, @coin3)
# expect(@change_maker.coin_counter(remaining_cents, @coin2)).to eq(remaining_cents % @coin2.value)
# end
# it "returns no remaining cents for one-value coin" do
# remaining_cents = @change_maker.remaining_change_count(@starting_cents, @coin3)
# remaining_cents = @change_maker.remaining_change_count(remaining_cents, @coin2)
# expect(@change_maker.coin_counter(remaining_cents, @coin1)).to eq(0)
# end
# it "logs the name and count of largest coin in coin_count on first execution" do
# expect { @change_maker.coin_counter(@starting_cents, @coin3) }
# .to change { @change_maker.coin_count }
# .from({})
# .to({
# eightsie: 4
# })
# end
# it "logs the name and count of second largest coin in coin_count on second execution" do
# remaining_cents = @change_maker.coin_counter(@starting_cents, @coin3)
# expect { @change_maker.coin_counter(remaining_cents, @coin2) }
# .to change { @change_maker.coin_count }
# .from({eightsie: 4})
# .to({eightsie: 4, threesie: 2})
# end
# it "logs the name and count of smallest coin in coin_count on last execution" do
# remaining_cents = @change_maker.coin_counter(@starting_cents, @coin3)
# remaining_cents = @change_maker.coin_counter(remaining_cents, @coin2)
# expect { @change_maker.coin_counter(remaining_cents, @coin1) }
# .to change { @change_maker.coin_count }
# .from({eightsie: 4, threesie: 2})
# .to({eightsie: 4, threesie: 2, onesie: 1})
# end
# end
# describe "#make_change" do
# it "should send message to coin_counter with starting_cents and largest coin" do
# coin_counter = double(@change_maker.coin_counter)
# @change_maker.make_change
# expect(coin_counter).to have_received()
# end
# end
# describe "#coin_counter" do
# it "returns 2 for 50 cents and coin_value 25" do
# expect(@change_maker.coin_counter(50, 25)).to eq(2)
# end
# it "returns 0 if coin_value is greater than cents count" do
# expect(@change_maker.coin_counter(25, 50)).to eq(0)
# end
# end
# describe "#coin_count" do
# it "it returns cents divided by coin_value and the remainder" do
# expect(coin_count(76, 25)).to eq([3,1])
# end
# end
class AmericanChangeMaker
AMERICAN_COINS = [Coin.new(name: :quarters, value: 25),
Coin.new(name: :dimes, value: 10),
Coin.new(name: :nickels, value: 5),
Coin.new(name: :pennies, value: 1)]
def initialize(change_maker)
@change_maker = change_maker.new(AMERICAN_COINS)
end
def make_change(cents)
@change_maker.make_change(cents)
end
end
class ChangeMaker
attr_reader :coin_count, :coins
def initialize(coins)
@coins = coins.sort_by(&:value).reverse
end
def make_change(cents)
@coins.reduce({}) do |coin_log, coin|
coin_log[coin.name] = coin.coin_count(cents)
cents = coin.remaining_cents(cents)
coin_log
end
end
end
class Coin
attr_reader :name, :value
def initialize(params)
@name = params[:name]
@value = params[:value]
end
def coin_count(cents)
cents / @value
end
def remaining_cents(cents)
cents % @value
end
end
describe Coin do
before {
@coin = Coin.new(name: "foobird", value: 67)
}
it "is initialized with name and value" do
expect(@coin.name).to eq "foobird"
expect(@coin.value).to eq 67
end
it "#coin_count takes cents and returns corresponding number of coins" do
expect(@coin.coin_count(137)).to eq 2
end
it "#remaining_cents takes cents and returns how many are left over" do
expect(@coin.remaining_cents(137)).to eq 3
end
it "#remaining_cents returns 0 when cents is evenly divisible by coin value" do
expect(@coin.remaining_cents(134)).to eq 0
end
end
describe ChangeMaker do
before {
@coins = [Coin.new(name: 'foobird', value: 5), Coin.new(name: "moobird", value: 10), Coin.new(name: "queuebird", value: 25)]
@change_maker = ChangeMaker.new(@coins)
}
it "#initialize will sort coins in descending order by value" do
expect(@change_maker.coins).to eq @coins.reverse
end
it "#make_change will call #coin_count on every coin" do
@coins.each { |coin| expect(coin).to receive(:coin_count).exactly(1).times }
@change_maker.make_change(32)
end
it "#make_change will call #remaining_cents on every coin" do
@coins.each { |coin| expect(coin).to receive(:coin_count).exactly(1).times }
@change_maker.make_change(32)
end
it "#make_change on first coin will call #coin_count with cents as an argument" do
expect(@coins[2]).to receive(:coin_count).with(67)
@change_maker.make_change(67)
end
it "#make_change on non-first coins will call #coin_count with the remaining cents from previous coin as an argument" do
@coins[2].stub(:remaining_cents => 25)
expect(@coins[1]).to receive(:coin_count).with(25)
@change_maker.make_change(40)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment