Skip to content

Instantly share code, notes, and snippets.

@mikeebert
Created March 19, 2012 21:35
Show Gist options
  • Save mikeebert/2127291 to your computer and use it in GitHub Desktop.
Save mikeebert/2127291 to your computer and use it in GitHub Desktop.
Coin Changer Kata
# Spec Step 1
describe CoinChanger do
it "should return a penny" do
CoinChanger.make_change(1).should == %w(p)
end
end
# Class Step 1 - after failed uninitialized constant, failed no method errors, failed wrong number of arguments and
# failed 'got nil expected ["p"]'
class CoinChanger
def self.make_change(n)
["p"]
end
end
# Spec Step 2
describe CoinChanger do
it "should return a penny" do
CoinChanger.make_change(1).should == %w(p)
end
it "should return two pennies" do
CoinChanger.make_change(2).should == %w(p p)
end
end
# Class Step 2 - after failed 'got ["p"] expected ["p" "p"]
class CoinChanger
def self.make_change(n)
if n == 1
["p"]
else
%w(p p)
end
end
end
# Spec Step 3
describe CoinChanger do
it "should return a penny" do
CoinChanger.make_change(1).should == %w(p)
end
it "should return two pennies" do
CoinChanger.make_change(2).should == %w(p p)
end
it "should return three pennies" do
CoinChanger.make_change(3).should == %w(p p)
end
end
# Class Step 3 - after failed 'got ["p" "p"] expected ["p" "p" "p"]'
class CoinChanger
def self.make_change(n)
change = []
n.each do |penny|
change << "p"
end
return change
end
end
# Class Refactor 1 - Wait a minute, that block is ugly! I'm not even using the "penny" variable
class CoinChanger
def self.make_change(n)
change = []
n.times {change << "p"}
return change
end
end
#Spec Step 4
describe CoinChanger do
..previous three tests..
it "should return a nickel" do
CoinChanger.make_change(5).should == %w(n)
end
end
# Class Step 4 - after failed 'got ["p" "p" "p" "p" "p"] expected ["n"]'
class CoinChanger
def self.make_change(n)
change = []
if n == 5
change << "n"
else
n.times {change << "p"}
end
return change
end
end
# Spec Refactor 1 - my fingers are getting tired of typing all the "it should" and CoinChanger.make_change(n)
# when the only things that are changing on each test is the amount of money we want to make change for and the
# array of the coins. I'm going to create a block with two variables to represent the amount and the coins and then
# interpolate those variables right into the text of my "it should" statement.
describe CoinChanger do
[[1, %w(p)],
[2, %w(p p)],
[3, %w(p p p)],
[5, %w(n)]
].each do |amount, coins|
it "should return #{coins} for #{amount} cent(s)" do
CoinChanger.make_change(amount).should == coins
end
end
end
# Spec Step 5
describe CoinChanger do
[..previous amounts..,
[6, %w(n p)]
].each do |amount, coins|
it "should return #{coins} for #{amount} cent(s)" do
CoinChanger.make_change(amount).should == coins
end
end
end
# Class Step 5 - after failed 'got ["n"] expected ["n" "p"]'
class CoinChanger
def self.make_change(n)
change = []
if n >= 5
change << "n"
n = n % 5
else
n.times {change << "p"}
end
return change
end
end
# Spec Step 6
describe CoinChanger do
[..previous amounts..,
[10, %w(d)]
].each do |amount, coins|
it "should return #{coins} for #{amount} cent(s)" do
CoinChanger.make_change(amount).should == coins
end
end
end
# Class Step 6 - after failed 'got ["n" "n"] expected ["d"]
class CoinChanger
def self.make_change(n)
change = []
if n >= 10
change << "d"
n = n % 10
end
if n >= 5
change << "n"
n = n % 5
end
n.times {change << "p"}
return change
end
end
# Spec Step 7
describe CoinChanger do
[[1, %w(p)],
[2, %w(p p)],
[5, %w(n)],
[6, %w(n p)],
[10, %w(d)],
[20, %w(d d)]
].each do |amount, coins|
it "should return #{coins} for #{amount} cent(s)" do
CoinChanger.make_change(amount).should == coins
end
end
end
# Class Step 7 - after failed 'got ["d"] expected ["d" "d"]
class CoinChanger
def self.make_change(n)
change = []
if n >= 10
amount = n / 10
amount.times {change << "d"}
n = n % 10
end
if n >= 5
change << "n"
n = n % 5
end
n.times {change << "p"}
return change
end
end
# Class Refactor 2 - There's a lot of repition going on up there... Based on the previous Spec refactor of using
# two variables in a block, I'm going to set up a Hash of coins where the key equals the amount and value is the
# coin. Then we'll go ahead and shovel in the number of coins of a denomnination into change, reset n to the
# remainder, and repeat the process for the next lowest denomination.
class CoinChanger
@coins = {10 => "d",
5 => "n",
1 => "p"}
def self.make_change(n)
change = []
@coins.each do |key, value|
amount = n / key
amount.times {change << value}
n = n % key
end
return change
end
end
# And at this point it's pretty much "solved". We can test for any amount with any denomination of coins and as
# long as those coins are listed in descending order in the @coins hash we will get the lowest number of coins back.
# "Final" Draft of Class and Spec
class CoinChanger
@coins = {25 => "q",
10 => "d",
5 => "n",
1 => "p"}
def self.make_change(n)
change = []
@coins.each do |key, value|
amount = n / key
amount.times {change << value}
n = n % key
end
return change
end
end
describe CoinChanger do
[[1, %w(p)],
[2, %w(p p)],
[5, %w(n)],
[6, %w(n p)],
[10, %w(d)],
[11, %w(d p)],
[16, %w(d n p)],
[20, %w(d d)],
[21, %w(d d p)],
[25, %w(q)],
[26, %w(q p)],
[30, %w(q n)],
[31, %w(q n p)],
[36, %w(q d p)],
[40, %w(q d n)],
[41, %w(q d n p)],
[50, %w(q q)]
].each do |number, change|
it "should return #{change} for #{number} cents" do
CoinChanger.make_change(number).should == change
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment