Home > OS >  Project Euler #10 [C ] sum of primes below 2000000
Project Euler #10 [C ] sum of primes below 2000000

Time:07-20

Prompt: The sum of the primes below 10 is 2 3 5 7 = 17. Find the sum of all the primes below two million.

Code:

#include <iostream>
#include <list>

/**
 * @brief Searches for numbers that in a that can be factored by b
 * 
 * @param a list of numbers
 * @param b factorable number
 */
void search(std::list<long long>& a, long long b, std::list<long long>::iterator c);

int main() {
    std::list<long long> nums;
    long long range = 0;
    long long PrimesSum = 0;

    std::cout << "Sum all the primes up to: ";
    std::cin >> range;

    for (int i = 2; i <= range; i  ) {
       nums.push_back(i);
    }

    for (std::list<long long>::iterator it = nums.begin(); it != nums.end(); it  ) {
        search(nums,*it,it);
    }
    
    for (std::list<long long>::iterator it = nums.begin(); it != nums.end(); it  ) {
        PrimesSum =*it;
    }
    std::cout << "The sum of all primes below " << range << " is " << PrimesSum << ".\n";
}

void search(std::list<long long>& a, long long b, std::list<long long>::iterator c) {
    std::list<long long>::iterator it = c;
    while (it != a.end()) {
        if (*it % b == 0 && *it != b) {
            a.erase(it);
        }
        it  ;
    }
}

Problem: I am getting a segmentation fault for values above 46998. Anything equal to or less than 46998 will work as expected. Could I get some help as to what I'm doing wrong or what I can improve?

CodePudding user response:

In fact there is no need to define a list to calculate the sum of prime numbers.

Nevertheless if to use your approach then within the function search after the statement

a.erase(it);

the iterator it becomes invalid.

You should write

while (it != a.end()) {
    if (*it % b == 0 && *it != b) {
        it = a.erase(it);
    }
    else
    {  
        it  ;
    }
}

Or you could write

  it;
while (it != a.end()) {
    if (*it % b == 0) {
        it = a.erase(it);
    }
    else
    {  
        it  ;
    }
}

Pay attention to that instead of this for loop

for (std::list<long long>::iterator it = nums.begin(); it != nums.end(); it  ) {
    PrimesSum =*it;
}

you could use standard algorithm std::accumulate declared in the header <numeric>

PrimesSum = std::accumulate( nums.begin(), nums.end(), 0ll );

Using the approach with a list I would write the program the following way

#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
#include <numeric>

int main()
{
    unsigned int range = 10'000;

    std::list<unsigned int> primes;

    for ( unsigned int i = 1; i   < range; )
    {
        if ( std::find_if( std::begin( primes ), std::end( primes ),
             [&i] ( const auto &item ) { return  i % item  == 0; } ) ==
             std::end( primes ) )
        {
            primes.push_back( i );
        }            
    }

    auto sum = std::accumulate( std::begin( primes ), std::end( primes ), 0llu );

    std::cout << "There are " << primes.size() 
              << " prime numbers.\nTheir sum is " 
              << sum << '\n';
}

The program output is

There are 1229 prime numbers.
Their sum is 5736396
  • Related