-3

I'm trying to code a function which has an unsigned int as output, and two unsigned ints as inputs. Now since this function has been defined recursively, i was trying to implement memoization using std::map to increase the time efficiency.

code:

unsigned memo_ack(unsigned m,unsigned n)

{

    static map <pair<int,int>,unsigned> mem;
    unsigned ans;
    if(m==0)
        return n+1;
    else if(n==0)
        if(mem.count(ackpair<m,n>)>0)


}

Here, I wish to use the count function to see whether a particular value with inputs (m,n) is present or not.

For example, if the count function returns > 0, then, the function will just return the stored value of the function, which has previously been calculated, so that there is no need of recalculation. If the count function returns zero, the original function calculates the value corresponding to that pair using the function definition.

Here's the problem: The count function won't accept std::pair as argument, nor will it accept two input arguments. How else do I tell the count function to count the number of occurrences of a particular input pair, and if it already exists, return a positive number(1, in this case)?

On passing a std::pair, I get the following error: Invalid operands to binary expression ('pair' and 'unsigned int')

The original non-memoized recursive solution was :

#include<iostream>

using namespace std;

int myAckermann(int m, int n)

{

    if(m==0)
        return n+1;
    else if (n==0)
        return myAckermann(m-1,1);
    else
        return myAckermann(m-1,myAckermann(m,n-1));
}

int main()

{

    int m,n;
    cin>>m>>n;
    long long ans;
    ans = myAckermann(m,n);
    cout<<ans;
    return 0;
}

1 Answers1

2

You can search the map using find for a key build from all your input parameters and return the value you found. If there is no value in the map/mem you calculate it, store it in the map for later and return it.

#include <map>

unsigned int memo_ack(unsigned int m, unsigned int n)
{
    static std::map <std::pair<unsigned int, unsigned int>, unsigned int> mem;
    unsigned ans = 0;
    if (m == 0) {
        return n+1;
    } else if (n == 0) {
        auto found = mem.find({ m, n }); // look-up whether we already provided an answer for these paramaters
        if (found != mem.end()) {
            ans = found->second;         // already know the answer
        } else {
            ans = 42;                    // Find the answer
            mem[{ m, n }] = ans;         // and keep it for later
        }
    }
    return ans;
}

You can still use std::map::count() like:

    int c = mem.count(std::make_pair(m, n));

but you do not really need the count and you'll have to search the value anyway.

You could also consider std::unordered_map which has almost constant complexity.


Here a version:

#include <map>

unsigned int memo_ack(unsigned int m, unsigned int n)
{
    static std::map <std::pair<unsigned int, unsigned int>, unsigned int> mem;
    unsigned ans = 0;
    if (m == 0) {
        return n+1;
    } else if (n == 0) {
        std::map<std::pair<unsigned int, unsigned int>, unsigned int>::const_iterator found = mem.find(std::make_pair(m, n));
        if (found != mem.end()) {
            ans = found->second;
        } else {
            ans = 42;
            mem[std::make_pair(m, n)] = ans;
        }
    }
    return ans;
}
Mihayl
  • 3,821
  • 2
  • 13
  • 32