Change Making Problem: Finding Ways to Make Change with Different Coins, Study notes of Computer Science

A problem in computer science about finding the number of ways to make change for a given amount of money using pennies, nickels, dimes, and quarters. The recursive approach to solve the problem and points out its limitations. It then proposes an alternative solution using dynamic programming to avoid repetitive method calls and improve performance.

Typology: Study notes

Pre 2010

Uploaded on 11/08/2009

koofers-user-8i9-1
koofers-user-8i9-1 🇺🇸

8 documents

1 / 8

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
The Change Problem
"The Change Store" was an old SNL skit (a pretty dumb
one...) where they would say things like, "You need change for
a 20? We'll give you two tens, or a ten and two fives, or four
fives, etc."
If you are a dorky minded CS 2 student, you might ask
yourself (after you ask yourself why those writers get paid so
much for writing the crap that they do), "Given a certain
amount of money, how many different ways are there to make
change for that amount of money?"
Let us simplify the problem as follows:
Given a positive integer n, how many ways can we make
change for n cents using pennies, nickels, dimes and quarters?
Recursively, we could break down the problem as follows:
To make change for n cents we could:
1) Give the customer a quarter. Then we have to make change
for n-25 cents
2) Give the customer a dime. Then we have to make change for
n-10 cents
3) Give the customer a nickel. Then we have to make change
for n-5 cents
4) Give the customer a penny. Then we have to make change
for n-1 cents.
If we let T(n) = number of ways to make change for n cents, we
get the formula
T(n) = T(n-25)+T(n-10)+T(n-5)+T(n-1)
pf3
pf4
pf5
pf8

Partial preview of the text

Download Change Making Problem: Finding Ways to Make Change with Different Coins and more Study notes Computer Science in PDF only on Docsity!

The Change Problem

"The Change Store" was an old SNL skit (a pretty dumb one...) where they would say things like, "You need change for a 20? We'll give you two tens, or a ten and two fives, or four fives, etc."

If you are a dorky minded CS 2 student, you might ask yourself (after you ask yourself why those writers get paid so much for writing the crap that they do), "Given a certain amount of money, how many different ways are there to make change for that amount of money?"

Let us simplify the problem as follows:

Given a positive integer n, how many ways can we make change for n cents using pennies, nickels, dimes and quarters?

Recursively, we could break down the problem as follows:

To make change for n cents we could:

  1. Give the customer a quarter. Then we have to make change for n-25 cents
  2. Give the customer a dime. Then we have to make change for n-10 cents
  3. Give the customer a nickel. Then we have to make change for n-5 cents
  4. Give the customer a penny. Then we have to make change for n-1 cents.

If we let T(n) = number of ways to make change for n cents, we get the formula

T(n) = T(n-25)+T(n-10)+T(n-5)+T(n-1)

Is there anything wrong with this?

If you plug in the initial condition T(1) = 1, T(0)=1, T(n)=0 if n<0, you'll find that the values this formula produces are incorrect. (In particular, for this recurrence relation T(6)=3, but in actuality, we want T(6)=2.)

So this can not be right. What is wrong with our logic? In particular, it can been seen that this formula is an OVERESTIMATE of the actual value. Specifically, this counts certain combinations multiple times. In the above example, the one penny, one nickel combination is counted twice. Why is this the case? The problem is that we are counting all combinations of coins that can be given out where ORDER matters. (We are counting giving a penny then a nickel separately from giving a nickel and then a penny.)

We have to find a way to NOT do this. One way to do this is IMPOSE an order on the way the coins are given. We could do this by saying that coins must be given from most value to least value. Thus, if you "gave" a nickel, afterwards, you would only be allowed to give nickels and pennies.

Using this idea, we need to adjust the format of our recursive computation:

To make change for n cents using the largest coin d, we could

1)If d is 25, give out a quarter and make change for n-25 cents using the largest coin as a quarter. 2)If d is 10, give out a dime and make change for n-10 cents using the largest coin as a dime. 3)If d is 5, give out a nickel and make change for n-5 cents using the largest coin as a nickel.

Our array could look like this

Essentially, each row label stands for the number of cents we are making change for and each column label stands for the largest coin value allowed to make change.

Now, let us try to write some code that would emulate building this table by hand, from left to right.

public static int makeChangedyn(int n, int d) {

// Take care of simple cases. if (n < 0) return 0; else if ((n>=0) && (n < 5)) return 1;

// Build table here. else {

int[] denominations = {1, 5, 10, 25}; int[][] table = new int[4][n+1];

// Initialize table for (int i=0; i<n+1;i++) table[0][i] = 1; for (int i=0; i<5; i++) { table[1][i] = 1; table[2][i] = 1; table[3][i] = 1; } for (int i=5;i<n+1;i++) { table[1][i] = 0; table[2][i] = 0; table[3][i] = 0; }

// Fill in table, row by row. for (int i=1; i<4; i++) { // Iterate through 3 rows for (int j=5; j<n+1; j++) { // Iterate through all cols for (int k=0; k<=i; k++) { // Iterate through all // coin possibilities.

// Only add if the coin isn't too big, also // prevents array out of bounds errors. if ( j >= denominations[k]) table[i][j] += table[k][j - denominations[k]]; } } } return table[lookup(d)][n]; } }

The idea shown above is an example of a reduction. A reduction is where you show that one problem is solvable, given that you have a solution to another problem. (This is a simplification, but one that will do for introducing the idea.)

Now, let's consider solving the problem on its own using a recursive solution:

The maximum sequence either includes numbers[index] or does NOT include numbers[index]. (Note that it can only include numbers[index] if numbers[index] > min.)

If it does include numbers[index], then the maximum length sequence has the length

1 + maxincseq(numbers, index+1, numbers[index]).

If it does NOT include numbers[index], then the maximum length sequence has the length

maxincseq(numbers,index+1,min);

Now that we have this characterization, we can generate the following:

public static int maxincseq(int[] numbers, int index, int min) {

if (index >= numbers.length) return 0; else if (numbers[index] <= min) return maxincseq(numbers, index+1, min); else return max(maxincseq(numbers, index+1, min), 1+maxincseq(numbers, index+1, numbers[index]); }

Use this recursive solution to come up with a dynamic programming solution to the problem. Your dynamic programming solution should only take in one parameter: the array.