0

I have an integer 153, and I need to determine whether or not he is equal to the sum of pow(digit, digits). so 153 = 1^3 + 5^3 + 3^3 = 153 returns true.

I chose to find the number of digits using a basic loop, then pushing all the integers into a vector so I could use the std::for_each function to iterate and use pow() on each of the elements.

The problem I am facing is the changing of each element. I don't want to resort to a for-loop yet, but I can't seem to figure out how to do it via the for_each.

Errors are commented in the code.

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <numeric>

bool narcissistic(int value)
{
    int k{};
    std::vector <int> sum{};
    while (value > 0) {
        k++;
        sum.push_back(value % 10);
        value /= 10;
    }
    std::for_each(sum.begin(), sum.end(), [](int& n) {pow(n, k); }); // error: 'k' is not captured
                                                              // (warning) note: the lambd has no capture-default
    if (std::accumulate(sum.begin(), sum.end(), 0) == value) return true;
    return false;
}

int main() 
{
    std::cout << narcissistic(153) << std::endl;
    return 0;
}
JeJo
  • 30,635
  • 6
  • 49
  • 88
Nix
  • 77
  • 1
  • 10
  • 1
    Possible duplicate of [What is a lambda expression in C++11?](https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11) The error message gave you the key word "capture" -- look for that word in the answers. – JaMiT Aug 27 '19 at 03:41

2 Answers2

2

You can let the lambda function to capture k

  • by value (the lambda function gets a copy) by using [k](int &n) { pow(n, k); }
  • by reference by using [&k](int &n) { pow(n, k); }.

Read more about lambda captures at https://isocpp.org/wiki/faq/cpp14-language#lambda-captures

That being said, I wouldn't use a std::vector to solve your problem. You can directly use unsigned int k = std::floor(std::log10(n)) + 1; to get the number of digits in a number, and just accumulate the sum in your while loop. Make sure to check for n > 0 at the beginning though.

Dinesh
  • 449
  • 2
  • 5
2

but I can't seem to figure out how to do it via the for_each.

You have a couple of problems there

  • In the while-loop you are changing the original passed value here
    value /= 10;
    
    Therefore, latter you can not compare with it at the line.
    if(std::accumulate(sum.begin(),sum.end(),0) == value)
    
    You should preserve the original value for the latter comparison.
  • Secondly, you need to sum the pow(n, k) up not the sum vector as it only contains the individual digits of the passed value.
    double sum{};   // since, std::pow returns the floating points 
    std::for_each(powVec.begin(), powVec.end(), [k, &sum](int n) { sum += std::pow(n, k); });
    //                                                            ^^^^^^^^^^^^^^^^^^^^^ -> sum the powers of digits
    //                                                    ^^^^^^ -> no need of taking reference here
    //                                           ^^^^^^^^^ -> capture `k` by value, `sum` by reference
    
  • Thirdly, the std::accumulate(sum.begin(),sum.end(),0) == value is wrong as value would have been already 0 at this time and the std::accumulate returns the sum of the individual digits(which is not what you wanted)

That means, change the program to: (See online live)

bool narcissistic(const int value)
//                ^^^^ --> cons because, passed value can only read
{
    int k{};
    std::vector<int> powVec{}; // named as a vector of power of digits in the `value`
    int value_copy{ value };   // copy of original value
    while (value_copy > 0) {
        k++;
        powVec.push_back(value_copy % 10);
        value_copy /= 10;      // work with the copy of value
    }
    double sum{};  // since, std::pow returns the floating points
    std::for_each(powVec.begin(), powVec.end(),
        [k, &sum](int n) { sum += std::pow(n, k); });
    //   ^^^^^^^^-->capture `k` by value `sum` by reference
    // if (std::accumulate(sum.begin(), sum.end(), 0) == value) return true; // not required
    return static_cast<int>(sum) == value;
}

You can read more about the lambdas here:

JeJo
  • 30,635
  • 6
  • 49
  • 88