Coin Sums
In my earlier post on how to solve Coin Sums, I presented an efficient solution. However, I did not get to this efficient solution right away. I’ve put four different versions of Coin Sums on JSPerf to show their various performances.
Explanation
Here is additional information about the choices made to improve algorithm efficiency.
First Version with Object
I started thinking about this problem as a combinatorics problem and therefore designed it to be similar to the recursive version of the Rock Paper Scissors solution. Compare the solution below to that solution.
However, you can’t write this solution exactly like Rock Paper Scissors. If you did, you would count ‘1p,2p’ and ‘2p,1p’ as two different ways for the coins to sum up to 3p, for example. I included a constraint that once we start putting a coin in a ‘pile’ of coins, we should only continue putting coins of equal or greater value into that pile. This gives us ‘1p,2p’ but not ‘2p,1p’. This constraint is
in the code below.1
coins[coin] >= lastCoin
The most surprising thing about the performance of this version is how incredibly slow this version was. Before using JSPerf, I did a quick test using the Chrome Dev Tools console. It took 17761 ms to run
. This is an incredibly inefficient way of doing this problem!1
makeChange(200)
First Version with Array
I knew that there was no reason to use an object to store the values of the coins so the first thing I did was swap the object for a simple array.
The new code looks like this:
This change in the data strcuture alone dropped the runtime in the Chrome Dev Tools console from 17761 ms down to 128 ms for
!1
makeChange(200)
Second Version
In this version, instead of using the constraint
which has us ignore certain coins, let’s reduce the array itself so that we’ll be iterating over fewer items in total.1
coins[coin] >= lastCoin
With these modifications, the quick runtime test in the Chrome Dev Tools console further reduced from 128 ms to 24 ms for
. This is great progress. But we’re not done yet!1
makeChange(200)
Third Version
In the second version, the
array was being mutated with 1
coinsLeft
. This is not ideal. And we actually don’t want to copy the 1
pop()
array (as when using 1
coinsLeft
) since this is a linear algorithm. Instead, the third version uses the original 1
slice()
array and keeps track of the coin we want to add to our ‘piles’ by using an index. This third version is the one explained in the Coin Sums post.1
coins
The quick runtime test went from 24 ms for
to 2ms. With this version I was finally satisfied with the algorithm’s performance. Check out the JSPerf on Coin Sums!1
makeChange(200)
UPDATE
Added some additional tests to the JS Perf.