jeudi 25 avril 2019

Can you capture a reference in a recursive lambda?

I've fully solved a particular problem on HackerRank (https://www.hackerrank.com/challenges/ctci-recursive-staircase/problem) using a recursive solution with memoization:

std::map<int, int> memoize;

int davis_staircase(int n) {
    if (n == 0) {
        return 1;
    } else if (n < 0) {
        return 0;
    }

    auto find = memoize.find(n);
    if (find != memoize.end()) {
        return find->second;
    }

    int num_steps = davis_staircase(n - 1) + davis_staircase(n - 2) + davis_staircase(n - 3);
    memoize[n] = num_steps;

    return num_steps;
}

I would like to hide the global std::map (without using a class) that I'm using as the lookup and thought I'd try creating a lambda that I can call recursively and also capture the cache/map by reference. I've tried the following:

int davis_staircase_2(int n) {

    std::map<int, int> memo;

    //auto recurse = [&memo](int n) -> int {                    // attempt (1)
    //std::function<int(int)> recurse = [&memo](int n) -> int { // attempt (2)
    std::function<int(std::map<int, int>&, int)> recurse = [](std::map<int, int>& memo, int n) -> int { // attempt (3)
        if (n == 0) {
            return 1;
        } else if (n < 0) {
            return 0;
        }

        auto find = memo.find(n);
        if (find != memo.end()) {
            return find->second;
        }

        //int num_steps = recurse(n - 1) + recurse(n - 2) + recurse(n - 3); // attempt (1) or (2)
        int num_steps = recurse(memo, n - 1) + recurse(memo, n - 2) + recurse(memo, n - 3); // attempt (3)

        memo[n] = num_steps;

        return num_steps;
    };

    //return recurse(n); // attempt (1) or (2)
    return recurse(memo, n); // attempt (3)
}

I have 3 slightly different attempts interleaved above but I cannot get any to compile. Is what I'm trying to do, possible?

I'm using clang on MacOS:

Apple LLVM version 10.0.0 (clang-1000.10.44.4)
Target: x86_64-apple-darwin18.2.0
Thread model: posix

Aucun commentaire:

Enregistrer un commentaire