From 1b0404554d45e448ddd850657c0289e22ff5783e Mon Sep 17 00:00:00 2001 From: Vishal Pankaj Chandratreya <19171016+tfpf@users.noreply.github.com> Date: Sun, 11 Feb 2024 12:59:26 +0530 Subject: [PATCH] P31: bottom-to-top dynamic programming. --- src/solutions/coin_sums.rs | 63 +++++++++++++++----------------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/src/solutions/coin_sums.rs b/src/solutions/coin_sums.rs index 5684e7b7..5b80a1e9 100644 --- a/src/solutions/coin_sums.rs +++ b/src/solutions/coin_sums.rs @@ -1,45 +1,30 @@ -struct CacheMap { - map: std::collections::HashMap<(usize, i32), i32>, - denominations: [i32; 8], -} -impl CacheMap { - fn new(denominations: [i32; 8]) -> CacheMap { - CacheMap { - map: std::collections::HashMap::new(), - denominations, - } +pub fn solve() -> i64 { + let denominations = [1, 2, 5, 10, 20, 50, 100, 200]; + + // Any element in this matrix be the number of ways to obtain a sum equal + // to the column index using coins at indices less than or equal to the row + // index. + let (rows, cols) = (denominations.len(), denominations.iter().max().unwrap() + 1); + let mut ways = vec![vec![0; cols]; rows]; + + // Bottom-up dynamic programming. + for idx in 0..rows { + ways[idx][0] = 1; } - /// Count the number of ways to obtain the remaining amount of money using - /// denominations at the given index and above. - /// - /// * `key` - Tuple of the index and remaining amount. - /// - /// -> Number of ways. - fn get(&mut self, key: (usize, i32)) -> i32 { - let (index, remaining) = key; - if index >= 8 || remaining < 0 { - return 0; - } - if remaining == 0 { - return 1; - } - match self.map.get(&key) { - Some(&value) => value, - None => { - let without = self.get((index + 1, remaining)); - let with = self.get((index, remaining - self.denominations[index])); - let value = without + with; - self.map.insert(key, value); - value - } + for sum in 1..cols { + ways[0][sum] = if sum % denominations[0] == 0 { 1 } else { 0 }; + } + for idx in 1..rows { + for sum in 1..cols { + ways[idx][sum] = ways[idx - 1][sum] + + if sum >= denominations[idx] { + ways[idx][sum - denominations[idx]] + } else { + 0 + }; } } -} - -pub fn solve() -> i64 { - let denominations = [1, 2, 5, 10, 20, 50, 100, 200]; - let mut cache_map = CacheMap::new(denominations); - let result = cache_map.get((0, 200)); + let result = ways[rows - 1][cols - 1]; assert_eq!(result, 73682); result as i64