What is Happening to my Sieve of Eratosthenes Program? - c++

I'm trying to solve a challenge question of summing all primes under 2 million. Knowing full well a naive approach would take too long, I decided to implement The Sieve of Eratosthenes with a counter to record the sum. It works for up to 512500 after which I receive this error:
Is the input size just too big for code to handle? If that's the case, how can I improve my code to avoid this error. If that's not possible, what is a better algorithm to implement for these purposes?
Here is my header code:
#ifndef NUMBERSIEVE_H
#define NUMBERSIEVE_H
class NumberSieve
{
public:
NumberSieve();
virtual ~NumberSieve();
int EratosthenesSieve(int num);
private:
void SetSieve(int nums[],int Size);
int current_prime;
int current_prime_address;
void updateSieve(int nums[],int Size,int start);
bool updateCurrentPrime(int nums[],int Size,int start);
bool notComplete;
void printSieve(int nums[],int Size);
int primeSum;
};
#endif // NUMBERSIEVE_H
Here is my implementation file:
#include "NumberSieve.h"
#include <cstdlib>
#include <iostream>
NumberSieve::NumberSieve()
{
//ctor
}
NumberSieve::~NumberSieve()
{
//dtor
}
void NumberSieve::SetSieve(int nums[],int Size)
{
for(int i=0;i<Size;i++)
{
nums[i]=(i+1);
}
nums[0]=0;//Sets the first composite number 1 to 0. We use 0 as an analogy for "crossing out numbers in the Sieve".
}
void NumberSieve::updateSieve(int nums[],int Size,int start)
{
int CURRENT_PRIME=nums[start];
for(int i=start;i<Size;i++)
{
if(nums[i]%CURRENT_PRIME==0)
{
nums[i]=0;
}
}
nums[start]=CURRENT_PRIME;
}
bool NumberSieve::updateCurrentPrime(int nums[],int Size,int start)
{
for(int i=start+1;i<Size;i++)
{
if(nums[i]!=0)
{
primeSum+=nums[i];
current_prime=nums[i];
current_prime_address=i;
return true;
}
}
return false;
}
void NumberSieve::printSieve(int nums[],int Size)
{
for(int i=0;i<Size;i++)
{
std::cout<<nums[i]<<std::endl;
}
}
int NumberSieve::EratosthenesSieve(int num)
{
int Eratosthenes[num];
int primeSum=0;
SetSieve(Eratosthenes,num);
current_prime=2;
primeSum+=2;
current_prime_address=1;
updateSieve(Eratosthenes,num,current_prime_address);
notComplete=updateCurrentPrime(Eratosthenes,num,current_prime_address);
while(notComplete)
{
updateSieve(Eratosthenes,num,current_prime_address);
notComplete=updateCurrentPrime(Eratosthenes,num,current_prime_address);
}
return primeSum;
}

My best guess is stackoverflow, because of this:
int Eratosthenes[num];
Instead try getting it from the free store:
int* Eratosthenes = new int[num]
Update the rest of the code accordingly
If you are not comfortable with pointers, a vector might be another option.

Related

Binary search optimisation

I implemented binary search in two ways and wondering which is more efficient? please help me know which is more efficient and how can it further be optimized? is time complexity remains same in both approach? I am a beginner in programming.
approach 1;
#include<iostream>
using namespace std;
bool BinarySearch(int*a,int n,int s ){
if(n==1){
if(a[0]==s)
return true;
else
return false;
}
else{
if(s<a[n/2]){
int U[n/2];
for(int i=0;i<n/2;i++){
U[i]=a[i];
}
return BinarySearch(U,n/2,s);
}
else{
int V[n-n/2];
for(int i=0;i<n-n/2;i++){
V[i]=a[i+n/2];
}
return BinarySearch(V,n-n/2,s);
}
}
}
int main(){
int array[10]={2,4,6,8,10,12,14,16,18,22};
cout<<BinarySearch(array,10,9);
}
approach 2:
#include<iostream>
using namespace std;
bool Bsearch(int arr[],int s,int l,int x){
cout<<"calling bsearch with arguments "<<s<<' '<<l<<' '<<x<<endl;
if(l==1)
return arr[s]==x;
int h=l/2;
if(x<arr[s+h])
return Bsearch(arr,s,h,x);
else
return Bsearch(arr,s+h,l-h,x);
}
int main(){
int marks[11]={17,18,20,22,24,26,28,30,32,34,36};
cout<<Bsearch(marks,0,11,32);
}
Thanks in advance for the kind help.
Other posters are correct that variable-length arrays are not good C++. If you define your main() as:
int main() {
std::array<int> marks{17,18,20,22,24,26,28,30,32,34,36};
cout<<Bsearch(marks,0,32);
}
or:
int main() {
std::vector<int> marks{17,18,20,22,24,26,28,30,32,34,36};
cout<<Bsearch(marks,0,32);
}
then you can drop the pointer/length pair in the parameter list to your binary-search function. The function prototype becomes something like:
bool Bsearch(const std::array<int>& arr, int s, int x);

Segmentation fault: 11 in C++ IntVector

I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment

Is my array the cause of rapid cpu & memory build up?

My MCVC is compiling but is not functioning as intended. The goal is a genetic algorithm that performs the basics i.e. crossover,mutation,evolution. In the code I have provided should print out the good job statements but thats not the case. I am a new programmer, sorry.
My questions are:
1) The cpu and ram are rev'ed up, is this array declaration and implementation the cause for the uncontrolled spike?
std::array<std::auto_ptr<Individual>,50>myarray;
2) Is my 2.53 GHz Intel Core 2 Duo not up for it?
3) Should I cut down the amount of loops?
Any help is always welcomed !
Individual.h
#include <stdio.h>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <array>
#include <iostream>
class Individual
{
public:
inline int getRandomNumber(int min = 0, int max = 1)
{
srand(static_cast<unsigned int>(time(0)));
static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0);
return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}
private:
int defaultGeneLength = 64;
std::vector<char>genes;
int fitness = 0;
public:
Individual()
{
std::cout<<"Good Job";
}
//setters and getters
void generateIndividual();
void setDefaultGeneLength(int length);
char getGene(int index);
void setGene(int index, char value);
//public methods
unsigned int size();
int getFitness();
std::string toString();
};
Individual.cpp
#include "Individual.h"
void Individual::generateIndividual()
{
for (int i = 0; i < size(); i++)
{
genes.push_back(getRandomNumber());
}
}
//setters and getters
void Individual::setDefaultGeneLength(int length)
{
defaultGeneLength = length;
}
char Individual::getGene(int index)
{
return genes.at(index);
}
void Individual::setGene(int index, char value)
{
genes[index] = value;
fitness = 0;
}
//public methods
unsigned int Individual::size()
{
return genes.max_size();
}
int Individual::getFitness()
{
if(fitness == 0)
{
fitness = 1;
} return fitness;
}
std::string Individual::toString()
{
std::string geneString = "";
for (int i = 0; i < size(); i++)
{
geneString.append(getGene(i),1);
}
return geneString;
}
Population.h
#include "Individual.h"
class Population
{
std::array<std::auto_ptr<Individual>,50>myarray;
public:
Population(int populationSize, bool initialise)
{
std::cout<<"Good Job2";
if(initialise)
{
for (int i = 0; i < populationSize; ++i)
{
std::auto_ptr<Individual>newIndividual(new Individual());
myarray.at(i) = newIndividual;
myarray.at(i)->generateIndividual();
saveIndividual(i,*(myarray.at(i)));
}
}
std::cout<<"Good Job 3";
}
Individual getIndividual(int index);
Individual getFittest();
unsigned long size();
void saveIndividual (int index, Individual indiv);
~Population()
{
}
};
Population.cpp
#include "Population.h"
Individual Population::getIndividual(int index)
{
return *myarray.at(index);
}
Individual Population::getFittest()
{
Individual fittest = *myarray.at(0);
for (int i = 0; i < myarray.max_size(); i++)
{
if (fittest.getFitness() <= getIndividual(i).getFitness())
{
fittest = getIndividual(i);
}
}
return fittest;
}
unsigned long Population::size()
{
return myarray.max_size();
}
void Population::saveIndividual (int index, Individual indiv)
{
*myarray.at(index) = indiv;
}
Main.cpp
int main(int argc, const char * argv[]) {
Population *mypop = new Population(2,true);
delete mypop;
mypop = nullptr;
return 0;
}
unsigned int Individual::size()
{
return genes.max_size();
}
Your genes is a:
std::vector<char> genes;
The C++ standard defines std::vector::max_size() as follows:
distance(begin(), end()) for the largest possible container
It is not specified what "largest possible container" means. "Possible" could mean anything, like, if the system had a ten terabyte hard drive, so that the operating system could use the entire hard drive to page its virtual memory address space. That's certainly "possible", in some sense of the word. But it goes without saying that paging out ten terabytes will take a while.
With 64 bit gcc, the following simple program:
#include <iostream>
#include <vector>
int main()
{
std::vector<char> c;
std::cout << c.max_size() << std::endl;
return 0;
}
Produces the following output:
18446744073709551615
However, my chances of being able to actually create a vector of such size are not very good.
But let's get back to your code:
void Individual::generateIndividual()
{
for (int i = 0; i < size(); i++)
{
genes.push_back(getRandomNumber());
}
}
Ok. You must be feeling quite lucky. You believe that it will be possible for you to create a vector<char> that's max_size() big.
Are you quite sure about that?
I'm somewhat skeptical.

how to efficiently appraoch for SPOJ Square free numbers?

I tried my best to solve Spoj problem No Squares numbers but I'm getting (TLE). Please tell how to approach. I'm unable to find any proper approach. Here is my code:
#include <bits/stdc++.h>
using namespace std;
#define size 10000004
int mark[size+1];
void sieve()
{
for(int i=2,k;(k=i*i)<=size;++i)
{
for(int j=k;j<=size;j=j+k)
mark[j]=-1;
}
}
int fn(int a,int b,int c)
{
int i,j,k,cnt=0;
for(i=a;i<=b;++i)
{
j=i;
if(mark[j]!=-1)
{
while(j>0)
{
if(j%10==c)
{
cnt+=1;
break;
}
else
j=j/10;
}
}
}
return cnt;
}
int main()
{
sieve();
int t,a,b,c;
cin>>t;
for(int i=0;i<t;t++)
{
cin>>a>>b>>c;
cout<<fn(a,b,c)<<endl;
}
}

Array class in C++: How to use one method in another

I have a class for performing various array operations. I like to use my insert method in my populate method.
Can someone guide me on that? Here is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
const int MAX=5;
class array
{
private:
int arr[MAX];
public:
void insert(int pos, int num);
void populate(int[]);
void del(int pos);
void reverse();
void display();
void search(int num);
};
void array::populate(int a[])
{
for (int i=0;i<MAX;i++)
{
arr[i]=a[i];
}
}
void array::insert(int pos, int num)
{
for (int i=MAX-1;i>=pos;i--)
{
arr[i] = arr[i-1];
arr[i]=num;
}
}
void array::del(int pos)
{
for (int i=pos;i<MAX;i++)
{
arr[pos]=arr[pos + 1];
}
}
void array::display()
{
for (int i=0;i<MAX;i++)
cout<<arr[i];
}
void array::search(int num)
{
for (int i=0;i<MAX;i++)
{
if (arr[i]==num)
{
cout<<"\n"<<num<<" found at index "<<i;
break;
}
if (i==MAX)
{
cout<<num <<" does not exist!";
}
}
}
int main()
{
array a;
for (int j=0;j<MAX;j++)
{
a.insert(j,j);
}
a.populate(a);
a.insert(2,7);
a.display();
a.search(44);
system("pause");
}
I like to use my insert method in my
populate method. Can someone guide me
on that?
That would mean that instead of the straightforward and efficient "copy from one array to another" approach, you'd call insert for each value of the input with the correct index in place of the assignment.
To call a method on the current instance, from inside a method:
insert(x, y);
//or
this->insert(x, y);
Your code also contains an error, in that you pass a wrong type to populate in main. It expect int* (a real array), not an array object.
Please elaborate your question. If you just need a good container have a look at the STL (Standard Template Library) std::vector. It's part of the C++ standard and comes with your compiler.
If you want to learn how to write a custom class, please try to be more precise in your question.
Also consider the wealth of beginner tutorials available on the net, for example:
http://www.learncpp.com/
Here is a little example on how to write a custom class with one member function calling the other and accessing a private data member (note that inside a member function you can refer to any other member directly):
#include <iostream>
class Example
{
private:
int some_private_stuff;
public:
Example();
void function_a();
void function_b();
};
Example::Example(){
some_private_stuff = 1;
}
void Example::function_a(){
std::cout << "this is function a" << std::endl;
some_private_stuff = 2;
std::cout << "changed private_stuff to " << some_private_stuff << std::endl;
}
void Example::function_b(){
std::cout << "this is function b" << std::endl;
function_a();
}
int main() {
Example e;
e.function_b();
return 0;
}