Created
February 21, 2014 04:31
-
-
Save benneuman/9128796 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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