Algorithms-UCSanDiego

Data Structures and Algorithms by UCSanDiego

View project on GitHub

1. Money Change Again

https://en.wikipedia.org/wiki/Change-making_problem

Problem

Solutions

CPP

    #include <iostream>
    #include <vector>
    #include <unordered_map>
    #include <algorithm>
    #include <cassert>

    using namespace std;

    using Type = int;
    using Coins = vector< Type >;
    using Memo = unordered_map< int,int >;

    const auto INF{ 9999 };

    namespace TopDown {
        template<typename Type>
        class Solution {
        public:
            Type minCoins( const Coins &C, Type T, Memo memo = {} ){
                return go( C, T, memo );
            }
        private:
            Type go( const Coins &C, Type T, Memo &memo, Type ans = INF ){
                if( T == 0 )
                    return 0;
                if( memo.find( T ) != memo.end() )
                    return memo[ T ];
                for( auto coin: C ){
                    if( 0 <= T - coin ){
                        auto cnt = 1 + go( C, T - coin, memo );
                        ans = min( ans, cnt );
                    }
                }
                return memo[ T ] = ans;
            }
        };
    }
    namespace BottomUp {
        template< typename Type >
        class Solution {
        public:
            Type minCoins( const Coins& C, Type T ){
                using Collection = vector< Type >;
                Collection dp( T+1, INF );
                dp[ 0 ] = 0;
                for( auto i{ 1 }; i <= T; ++i )
                    for( auto coin: C )
                        if( 0 <= i - coin )
                            dp[ i ] = min( dp[ i ], 1 + dp[ i - coin ] );
                return dp[ T ];
            }
        };
    }

    int main() {
        TopDown::Solution< Type > rec_solution;
        BottomUp::Solution< Type > dp_solution;
        Coins C{ 1,3,4 };      // (C)oins
        auto T{ 0 }; cin >> T; // (T)arget
        auto rec_ans = rec_solution.minCoins( C, T );
        auto dp_ans = dp_solution.minCoins( C, T );
        assert( rec_ans == dp_ans );
        cout << rec_ans << endl;
        return 0;
    }

Python3

    from typing import List, Dict

    INF = 9999
    Type = int
    Coins = List[Type]
    Memo = Dict[Type,Type]

    class RECSolution:
        def minCoins( self, C: Coins, T: Type ) -> Type:
            return self.go( C, T )
        def go( self, C: Coins, T: Type, memo: Memo={}, ans: Type=INF ) -> Type:
            if T == 0:
                return 0
            if T in memo:
                return memo[ T ]
            for coin in C:
                if 0 <= T - coin:
                    cnt = 1 + self.go( C, T - coin, memo )
                    ans = min( ans, cnt )
            memo[ T ] = ans
            return ans
    class DPSolution:
        def minCoins( self, C: Coins, T: Type ) -> Type:
            dp = [ INF ] * ( T+1 )
            dp[ 0 ] = 0
            for i in range( T+1 ):
                for coin in C:
                    if 0 <= i - coin:
                        dp[ i ] = min( dp[ i ], 1 + dp[ i - coin ] )
            return dp[ T ]

    if __name__ == '__main__':
        rec_solution = RECSolution()
        dp_solution = DPSolution()
        C = [ 1,3,4 ]      # (C)oins
        T = int( input() ) # (T)arget
        rec_ans = rec_solution.minCoins( C, T )
        dp_ans = dp_solution.minCoins( C, T )
        assert( rec_ans == dp_ans )
        print( rec_ans )