I am learning myself C++ by solving problems from the Euler project. One of the exercises were to find the maximum prime factor, which I found the fastest way to solve was to use divide and conquer, using the following code snippet:
long primeFactor1(long n);
long primeFactor(long n)
{
long divisorR = findDivisor(n);
long divisorL = n/divisorR;
if (divisorR == n){
return divisorR;
}
long primeFactorDivL = primeFactor1(divisorL);
long primeFactorDivR = primeFactor1(divisorR);
return std::max(primeFactorDivL,primeFactorDivR);
}
long primeFactor1(long n)
{
std::cout << "Is "<<n<< " a prime? " << checkPrime(n) << std::endl;
if (checkPrime(n)){
return n;
}
else{
return primeFactor(n);
}
}
Where checkPrime is a function which checks it a number is a prime and findDivisor finds the smallest even divisor of a number n. So this program works nicely and gives and output instantly even for the number given in the problem (which was quite large, to say the least).
My problem is, however, I want to convert the program to return all the prime divisors instead of just the largest. Which means I basically have to change:
return std::max(primeFactorDivL,primeFactorDivR);
to something that concatenates the two instead and adjusts the functions such that they can return the array generated.
In Matlab which I come from I would just put square-brackets around s.t.
[primeFactorDivL,primeFactorDivR]
What is the best (preferably also easiest) way to do this in C++?
UPDATE:
I have tried implementing it using vectors, which can be seen in the code below using typecast at the leaves. However, trying to compile it I get the compilation error:
primeFactor.cpp:51:9: error: no viable conversion from 'typename
enable_if<__is_forward_iterator<__wrap_iter<long *> >::value && is_constructible<value_type, typename
iterator_traits<__wrap_iter<long *> >::reference>::value, iterator>::type' (aka
'std::__1::__wrap_iter<long *>') to 'std::vector<long>'
...primeFactorDivL.insert( primeFactorDivL.end(), primeFactorDivR.begin(), primeFactorDivR.end() );
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/vector:568:5: note: candidate constructor not
viable: no known conversion from 'typename enable_if<__is_forward_iterator<__wrap_iter<long *>
>::value && is_constructible<value_type, typename iterator_traits<__wrap_iter<long *>
>::reference>::value, iterator>::type' (aka 'std::__1::__wrap_iter<long *>') to 'const
std::__1::vector<long, std::__1::allocator<long> > &' for 1st argument
vector(const vector& __x);
^
1 error generated.
Where my code is now:
std::vector<long> primeFactor1(long n);
std::vector<long> primeFactor(long n)
{
long divisorR = findDivisor(n);
long divisorL = n/divisorR;
if (divisorR == n){
return std::vector<long>(divisorR);
}
std::vector<long> primeFactorDivL( primeFactor1(divisorL) );
std::vector<long> primeFactorDivR( primeFactor1(divisorR) );
return primeFactorDivL.insert( primeFactorDivL.end(), primeFactorDivR.begin(), primeFactorDivR.end() );
}
std::vector<long> primeFactor1(long n)
{
std::cout << "Is "<<n<< " a prime? " << checkPrime(n) << std::endl;
if (checkPrime(n)){
return std::vector<long>(n);
}
else{
return primeFactor(n);
}
}