|
1 | | -from typing import List |
| 1 | +from typing import List, Tuple, Dict |
| 2 | +from typing import List, Tuple, Dict |
2 | 3 |
|
3 | 4 |
|
4 | | -def ways_to_make_change(total: int) -> int: |
| 5 | +def ways_to_make_change(total: int) -> int: |
5 | 6 | """ |
6 | 7 | Given access to coins with the values 1, 2, 5, 10, 20, 50, 100, 200, returns a count of all of the ways to make the passed total value. |
7 | 8 |
|
8 | 9 | For instance, there are two ways to make a value of 3: with 3x 1 coins, or with 1x 1 coin and 1x 2 coin. |
9 | 10 | """ |
10 | | - return ways_to_make_change_helper(total, [200, 100, 50, 20, 10, 5, 2, 1]) |
| 11 | + return ways_to_make_change_helper( # Call the helper function with the total, the list of coin denominations, and an empty cache |
| 12 | + total, |
| 13 | + [200, 100, 50, 20, 10, 5, 2, 1], |
| 14 | + cache={} |
| 15 | + ) |
11 | 16 |
|
| 17 | +from typing import List, Tuple, Dict |
12 | 18 |
|
13 | | -def ways_to_make_change_helper(total: int, coins: List[int]) -> int: |
14 | | - """ |
15 | | - Helper function for ways_to_make_change to avoid exposing the coins parameter to callers. |
16 | | - """ |
17 | | - if total == 0 or len(coins) == 0: |
| 19 | + |
| 20 | +def ways_to_make_change(total: int) -> int: |
| 21 | + return ways_to_make_change_helper( |
| 22 | + total, |
| 23 | + [200, 100, 50, 20, 10, 5, 2, 1], |
| 24 | + cache={} |
| 25 | + ) |
| 26 | + |
| 27 | + |
| 28 | +def ways_to_make_change_helper( |
| 29 | + total: int, |
| 30 | + coins: List[int], |
| 31 | + cache: Dict[Tuple[int, Tuple[int, ...]], int] |
| 32 | +) -> int: |
| 33 | + |
| 34 | + # Convert coins list to tuple so it can be used as dict key |
| 35 | + key = (total, tuple(coins)) |
| 36 | + |
| 37 | + if key in cache: |
| 38 | + return cache[key] |
| 39 | + |
| 40 | + if total == 0: |
| 41 | + return 1 |
| 42 | + |
| 43 | + if len(coins) == 0: |
18 | 44 | return 0 |
19 | 45 |
|
20 | 46 | ways = 0 |
| 47 | + |
| 48 | + # Iterate through each coin denomination and count the number of ways to make change using that denomination |
| 49 | + # and the remaining coins |
21 | 50 | for coin_index in range(len(coins)): |
22 | 51 | coin = coins[coin_index] |
23 | 52 | count_of_coin = 1 |
24 | | - while coin * count_of_coin <= total: |
| 53 | + |
| 54 | + while coin * count_of_coin <= total: # While the total value of the current coin denomination multiplied by the count of that coin is less than or equal to the total, we can continue to count ways to make change using that denomination |
25 | 55 | total_from_coins = coin * count_of_coin |
26 | | - if total_from_coins == total: |
| 56 | + |
| 57 | + if total_from_coins == total: # |
27 | 58 | ways += 1 |
28 | 59 | else: |
29 | | - intermediate = ways_to_make_change_helper(total - total_from_coins, coins=coins[coin_index+1:]) |
30 | | - ways += intermediate |
31 | | - count_of_coin += 1 |
| 60 | + ways += ways_to_make_change_helper( # |
| 61 | + total - total_from_coins, |
| 62 | + coins[coin_index + 1:], |
| 63 | + cache |
| 64 | + ) |
| 65 | + |
| 66 | + count_of_coin += 1 # Increment the count of the current coin denomination to check for the next possible combination of coins |
| 67 | + |
| 68 | + cache[key] = ways |
32 | 69 | return ways |
| 70 | + |
0 commit comments