"Ways to make change for a dollar": How to optimize with constraints
The way I understand this, it seems to be the classic coin change problem with a few constraints which you have provided. Although if we try to consider all the subsets of the available coins this problem will definitely take exponential time in terms of number of coins available. (The size of the power-set , each subset has to be considered although few optimizations exist but still it doesn't reduce the time to polynomial). For reducing the time taken we can employ the optimization called memorization. 


  return change(list, (number - list[0])) + change(list[1:], number)


If you see the line closely in your solution you can see the problem has overlapping subproblems which will be computed again and again. For optimization we try to remember the results of the subproblems and return this precomputed result if we encounter the same sub-problem again.However, as you can guess there is a space-time trade-off here. For speeding up we need to remember the results for this we need atleast $\mathcal{O}({n})$ space (n is the sum which we are trying to make.).

For overlapping subproblems consider the example of making a sum of N using coins 2,3 and, 5.

Suppose solution is given by F(n), then 

let us choose the permutations i can make using 2: 

Then F(n) = 1+F(n-2) 

Now let us choose coin 3:

F(n) = 2+F(n-5)
.
.
.
.
 We calculate this quantity and return the result. 
However suppose if we choose 5 in the starting step.

then F(n) = 1+ F(n-5)

We now have to calculate F(n-5) again. Hence overlapping subproblems exist.  

For the constraints which you have mentioned we can add those constraints by maintaining a count of each coin as well as total count of the coins used at each step of the recursive call to our function (In the function which is named $change(list, number)$ in your implementation ) we can check the constraint and add zero as the result of that particular function call as it generated an invalid permutation. valid permutation contributes to a 1 in our function.
Our function will look something like this :

def change(list, number, countCoinsList, totCount):
if (number is 0):
    return 1
if (len(list) is 0):
    return 0
if (number &lt; list[0]):
    return 0
if(countCoinsList[i]&lt;8)
     countCoinsList[i]+=1 
     tmp1= change(list, (number - list[i]),countCoinsList,totCount+1)

 tmp2= change(list[i+1:], number,countCoinsList,totCount)
return  tmp1+tmp2;