So I need help with my code. For some reason it keeps crashing when I enter a number past 500,000. Here is the exact assignment.
Implement the Sieve of Eratosthenes and use it to find all prime
numbers less than or equal to one million. Use the result to
prove Goldbach's Conjecture for all even integers between four and
one million, inclusive.
Implement a function with the following declaration:
void sieve(int array[], int num);
This function takes an integer array as its argument. The array
should be initialized to the values 1 through 1000000. The
function modifies the array so that only the prime numbers remain;
all other values are zeroed out.
This function must be written to accept an integer array of any
size. You must should output for all primes numbers between 1 and
1000000, but when I test your function it may be on an array of a
different size.
Implement a function with the following declaration:
void goldbach(int array[], int num);
This function takes the same argument as the previous function
and displays each even integer between 4 and 1000000 with two
prime numbers that add to it.
The goal here is to provide an efficient implementation. This
means no multiplication, division, or modulus when determining if
a number is prime. It also means that the second function must find
two primes efficiently.
Output for your program:
All prime numbers between 1 and 1000000
and all even numbers between 4 and 1000000 and the two prime
numbers that sum up to it.
DO NOT provide output or a session record for this project!
And here is what I have so far. If anyone could help me that would be great.
#include <iostream>
using namespace std;
void sieve (int array[], int num);
int main()
{
int num;
cout << "Enter a number to calculate up to." << endl;
cin>> num;
if ( num < 2 )
return 0;
int array[num];
array[0]= array[1]= 0;
for ( int i= 2; i < num; ++i )
array[i]= i;
sieve(array,num);
for (int i=0; i<num; i++)
if (array[i] > 0)
cout << array[i] <<" "<<endl;
cout<<endl;
return 0;
}
void sieve( int array[], int num )
{
for ( int i= 0; i < num; ++i )
{
if ( array[i] != 0 )
{
for ( int j= i+i; j < num; j += i )
{
array[j]= 0;
}
}
}
}
The reason why your code crashes is that you're using VLA allocation for the array here
int array[num];
It's used to allocate num int elements of the stack, which is most probably too small to hold a million of int values.
You should note it's not a standard c++ feature, but an extension provided by a number of compiler implementations.
To fix this there are three alternatives:
You configure the stack size used for your program to be big enough to hold the number of int elements (this is OS dependend)
You use a std::vector<int> array(num); instead, that allocates these elements on the heap memory
You allocate the necessary memory on the heap yourself using int* array = new int[num]; and delete [] array; at the end of your program (I wouldn't recommend this solution, because it's prone to make silly mistakes regarding the proper memory management)
As I see this is an assignment, you need to write your own code, but I have a few ideas to reduce the amount of memory significantly.
Why don't you use array of bits instead ?
Do something like
#define IS_SET(x) (arr[(x)>>3] & (0x01 << ((x) & 0x07)))
#define SET(x) (arr[(x)>>3] |= (0x01 << ((x) & 0x07)))
and define arr as an array of char. This will make the memory utilization 8 folds down. For C++ you can use bool might not get you the lowest possible memory usage.
First clear out all the char elements. Then for each number set bits using SET(x) an once all marking is done. If IS_SET(x) evaluates false then x is prime.
Saves large amount of memory.
EDIT1:
Another trick to cut 50% of the memory required is not to retain space for the even numbers. Start with i=3 and always increment using i+=2 and mark the bit arrays. While reading do the same.
EDIT2:
If you can find a series which skips the integers which are multiple of two or three or both, then you can save around 30% more memory. In fact you can make such a series and skip storing and marking for the multiples of two and three or both.
Related
I have tried to solve the following problem: "n numbers are given. For every one of them, calculate the sum 1+(1+2)+(1+2+3)+...+(1+2+3+...+x) and output the results in a separate vector". I have gotten a formula for the sum and have implemented it into c++. The code seems to be working perfectly on vs code, but when I upload it to the website where I got the problem from I get 0 points, with the explanation: Caught fatal signal 11. I have read some articles but none of them have helped me crack the problem. Here is the code:
#include <iostream>
#define N 1000000
using namespace std;
int v[N], s[N];
int main()
{
int n, i;
cin >> n; // user inputs number of elements
for(i = 0; i < n; i++)
{
cin >> v[i]; // user inputs the elements
s[i] = v[i]*(v[i] + 1)*(v[i] + 2) / 6; // another vector is calculated using the formula
cout << s[i] << " ";
}
return 0;
}
Your problem is two fold. One, you're not using vectors, you're using C-style arrays. And two, you're running out of memory due to the size of your C-style arrays.
C-style arrays are allocated on the stack, and there is only limited memory on the stack. So if you allocate, say, two arrays of size, I don't know, 1000000, you might run into some memory issues.
On the other hand, C++ vectors are more modern, allow for dynamic resizing (useful for when you don't know how many elements you're going to have, I doubt you'll have 1000000), and it is also memory stored on the heap, giving you a lot more breathing room when it comes to memory.
Vectors work like this:
#include <vector>
std::vector<int> vec; // creates the vector
vec.push_back(5); // adds an element equal to 5 to the vector, vec size is now 1
vec.push_back(6); // adds an element equal to 6 to the vector, vec size is now 2
std::cout << vec[0]; // elements are accessed just like a C-style array
I am working on producing C++ code to list all primes between 1 and 100 say. In order to present my question I need to provide some background.
The basic idea of what I want to do is the following:
Introduce a vector to hold all the primes in ascending order. If the first j elements of this vector are given, the j+1 element is then given as the smallest integer larger than the j'th element which is not divisible by any of the first j elements. The first element is moreover given to be 2.
Thus if v denotes the vector of primes, I want to produce code which implements the following math-type argument;
v[1]=2;
for(2<i<=100)
if i % v[j] !=0 FOR ALL 0<j< v.size()
v.push_back(i)
else
do nothing
The problem I am facing however is that C++ doesn't seem to have a for all type language construct. In order to get around this I introduced a counter variable. More precisely:
int main() {
const int max=100;
vector<int>primes; // vector holding list of primes up to some number.
for(int i=2; i<=max;++i){
if(i==2)
primes.push_back(i); // inserts 2 as first prime
else{
double counter=primes.size(); // counter to be used in following loop.
for(int j=0;j<primes.size();++j){
if(i% primes[j]==0){
break; // breaks loop if prime divisor found!
}
else{
counter-=1; //counter starts at the current size of the primes vector, and 1 is deducted each time an entry is not a prime divisor.
}
}
if (counter==0) // if the counter reaches 0 then i has no prime divisors so must be prime.
primes.push_back(i);
}
}
for(int i=0; i<primes.size(); ++i){
cout << primes[i] << '\t';
}
return 0;
}
The questions I would like to ask are then as follows:
Is there a for-all type language construct in C++?
If not, is there a more appropriate way to implement the above idea? In particular is my use of the counter variable frowned upon?
(Bonus) Is anyone aware of a more efficient way to find all the primes? The above works relatively well up to 1,,000,000 but poorly up to 1 billion.
Note I am beginner to C++ and coding in general (currently working through the book of Stroustrup) so answers provided with that in mind would be appreciated.
Thanks in advance!
EDIT:
Hello all,
Thank you for your comments. From them I learned that both use of a counter and a for all type statement are unnecessary. Instead one can assign a true or false value to each integer indicating whether a number is prime with only integers having a true value added to the vector. Setting things up in this way also allows the process of checking whether a number is prime given the currently known'' primes to be independent of the process of updating the currently known'' primes. This consequently addresses another criticism of my code which was that it was trying to do too many things at once.
Finally it was pointed out to me that there are some basic ways of improving the efficiency of the prime divisor algorithm for finding primes by, for instance, discounting all even numbers greater than 2 in the search (implemented by starting the appropriate loop at 3 and then increasing by 2 at each stage). More generally it was noted that algorithms such as the sieve of Erastothenes are much faster for finding primes, as these are based on multiplication not division. Here is the final code:
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
vector<int> primes; // vector holding list of primes up to some number.
bool is_prime(int n) {// Given integer n and a vector of primes this boolean valued function returns false if any of the primes is a prime divisor of n, and true otherwise. In the context of the main function, the list of primes will be all those that precede n, hence a return of a true value means that n is itself prime. Hence the function name.
for (int p = 0; p < primes.size(); ++p)
if (n % primes[p] == 0) {
return false;
break; // Breaks loop as soon as the first prime divisor is found.
}
return true;
}
int main() {
const int max=100;
primes.push_back(2);
for (int i = 3; i <= max; i+=2)
if (is_prime(i) == true) primes.push_back(i);
for(int i=0; i<primes.size(); ++i)
cout << primes[i] << '\t';
return 0;
}
I just have one additional question: I checked how long the algorithm takes up to 1,000,000 and the presence of the break in the is_prime function (which stops the search for a prime divisor as soon as one is found) doesn't seem to have an effect on the time. Why is this so?
thanks for all the help!
I was trying to solve the problem Modulo strength at hackerearth ,
https://www.hackerearth.com/practice/basic-programming/implementation/basics-of-implementation/practice-problems/golf/modulo-strength-4/ , so basically we have to find all such pairs of no. (say i,j) such that A[i]%k=A[j]%k where k is a no. given in the question , i tried brute force approach and got time limit exceeded at some of the last test cases and in the discussion tab i found a code which is working but i couldn't understand what exactly it does, and the underlying thinking behind the algorithm used.
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
int n,k,s=0;
cin>>n>>k;
int a[n];
vector<int>v(k,0); // Specially this part ,what does it store?
for(int i=0;i<n;i++)
{
cin>>a[i];
v[a[i]%k]++;
}
for(int i=0;i<k;i++)
{
s+=v[i]*(v[i]-1);
}
cout<<s;
}
Here is the code, i wanted to understand it so that i can apply this logic over other problems.
There are a few problems with that;
"bits/stdc++.h" is not a standard header
Variable-length arrays, like int a[n], are non-standard and prone to runtime errors (this one is also completely unnecessary)
#define int long long makes the code have undefined behaviour.
Here is a fixed version, with some minor renaming and clarifying comments:
#include <iostream>
#include <vector>
int main() {
long long n, k;
cin >> n >> k;
// There are k groups of friends.
std::vector<int> friends(k);
// Count how many people there are in each group.
for(int i = 0; i < n; i++)
{
int x;
std::cin >> x;
friends[x%k]++;
}
long long sum = 0;
for(int i = 0; i < k; i++)
{
// In a group of N mutual friends, each person has N-1 friends.
sum += friends[i] * (friends[i]-1);
}
std::cout << sum;
}
Let's first go through with the purpose of every variable in the code.
The purpose of n,k,s is explicitly given.
a[n] is for reading the numbers in array.
std::vector<int>v(k,0) stores k sized vector of 0's, and v[i] indicates the number of variables in a[n] for which a[j]%k==i.
In the last loop, the following has done. The number of pairs that can be constructed with n elements is n*(n-1) (basic combinatorics), and if we have v[i] numbers for which the condition is satisfied and a[j]%k==i the number of pairs that can be constructed is v[i]*(v[i]-1). The loop sums up the number of pairs for every remnant i.
Well all I had to do was:
user has to enter 20 numbers.
and I should find from array numbers lower than the last number user entered ( 20 numbers )
Example :
User enters:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,4
Output should be:
1,2,3
according to me, my output is correct. But after 1,2,3 alot of 0 come in.
#include <iostream>
using namespace std;
int i,skaitlis,sk2,x;
int masivs[19];
int main() {
for ( i=0; i<=19; i++ )
{
cin >> masivs[i];
skaitlis = masivs[19];
}
for (i=0;i < sizeof masivs; i++){
if ( masivs[i]<skaitlis){
cout << masivs[i] <<endl;
}
}
}
The problem is here:
for (i=0;i < sizeof masivs; i++){
The sizeof operator returns the size of the array in bytes, not in number of elements. On normal modern systems the size of an int is four bytes, meaning sizeof masivs will give you 4*19.
That will lead the loop going massively out of bounds and give you undefined behavior.
Not to mention the other out of bounds you have in the previous loop.
Also, taking about the first loop, why have the assignment to skaitlis inside the loop? After you fix the out-of-bounds indexing, it will just assign zero (because masivs is a global variable and therefore initialized to all zeroes) except in the last iteration. You can move that assignment to be outside the loop.
I am having a truly bizarre problem with my code here. It works (seemingly) when I use manual print statements to output the values of int *primesArr, but if I try to do so with a for loop it fails. I ran it through gdb and find that it crashes right around where I set the next cell in the array to value 'k', which only occurs when a number is prime. The first iteration is successful (i.e. 2 is set to primesArr[0]) and then the program Segfaults when trying to increment the array. But this only happens when using a for-loop. When I create individual print statements, my program works as expected. I'm not sure how/why I am accessing memory that hasnt been appropriated when using a for-loop. I'm sure I've performed some amateur mistake somewhere, and it probably has something to do with how I'm passing my pointer... but I cannot determine its exact root. I'd appreciate any help and thank you in advance.
#include<stdio.h>
int genPrimes(int seed, int *test){
int inNumPrimes=0;
for(int k=0; k<=seed; k++){//k is number being checked for primeness
int cnt=0;
for(int i=1; i<=k; i++){//'i' is num 'k' is divided by
if(k%i == 0){
cnt++;
if(cnt > 2){
break;
}
}else{
}
}
if(cnt == 2){
printf("%i IS PRIME\n",k);
*test=k;
test++;//according to gdb, the problem is somewhere between here
inNumPrimes++;//and here. I'd wager I messed up my pointer somehow
}
//printf("%i\n",k);
}
return inNumPrimes;
}
int main(){
int outNumPrimes=0;
int *primesArr;
int n = 0;
n=20;
outNumPrimes=genPrimes(n, primesArr);
printf("Congratulations! There are %i Prime Numbers.\n",outNumPrimes);
//If you print using this for loop, the SEGFAULT occurs. Note that it does not matter how high the limit is; its been set to many values other than 5. It will eventually be set to 'outNumPrimes'
//for(int a=0; a<5; a++){
//printf("%i\n",primesArr[a]);
//}
//If you print the array elements individually, the correct value--a prime number--is printed. No SEGFAULT.
printf("%i\n",primesArr[0]);
printf("%i\n",primesArr[1]);
printf("%i\n",primesArr[2]);
printf("%i\n",primesArr[3]);
printf("%i\n",primesArr[4]);
printf("%i\n",primesArr[5]);
printf("%i\n",primesArr[6]);
printf("%i\n",primesArr[7]);
//
return 0;
}
Output with manual statements:
$ ./a.out
2 IS PRIME
3 IS PRIME
5 IS PRIME
7 IS PRIME
11 IS PRIME
13 IS PRIME
17 IS PRIME
19 IS PRIME
Congratulations! There are 8 Prime Numbers.
2
3
5
7
11
13
17
19
Now with the for loop:
$ ./a.out
2 IS PRIME
Segmentation fault
you are passing an uninitialized pointer into your primes function. the behavior you get is undefined, which is why this seems so mysterious. the variable primesArr could be pointing to anywhere.
for a simple case like this, it'd probably be better to use a std::vector<int>
The line
int *primesArr;
Declares primesArr as a pointer variable but doesn't allocate any memory for it. Since the genPrimes() function expects to treat it as an empty array that will be filled with primes, you can allocate memory in main() before calling genPrimes():
int primesArr[MAX_PRIMES];
or
int *primesArr = malloc(MAX_PRIMES * sizeof(int));
In both cases, however, you must guarantee that MAX_PRIMES is large enough to hold all of the primes that genPrimes() finds, otherwise the code will generate an error just as it does now.
Other hints:
1: Complexity
The only reason cnt is necessary is that k is divisible by 1 and k. If you change
for (int i=1; i<=k; i++) { // 'i' is the number 'k' is divided by
to
for (int i=2; i<k; ++i) { // 'i' is the number 'k' is divided by
then both of those cases are eliminated, and the loop can exit as soon as it finds a value of i for which k%i == 0.
2: Efficiency
The test
for (int i=2; i<k; ++i) { // 'i' is the number 'k' is divided by
is still quite inefficient for two reasons. First, there's no need to test every even number; if k > 2 and (k % 2) == 0, then k cannot be prime. So you can eliminate half of the tests by checking explicitly for 2 (prime) or divisibility by 2 (not prime), and then using
for (int i = 3; i < k; i += 2) { // 'i' is the number 'k' is divided by
But you can make this still more efficient, because you can stop after reaching sqrt(k). Why? If k is divisible by some number i, then it must also be divisible by k/i (because i * k/i=k). And if i > sqrt(k), then k/i < sqrt(k) and the loop would already have exited. So you need only
int r = (int) sqrt(k);
for (int i = 3; i <= r; i += 2) { // 'i' is the number 'k' is divided by
If sqrt() isn't available, you can use
for (int i = 3; i*i <= k; i += 2) { // 'i' is the number 'k' is divided by
3: Style
Just a simple thing, but instead of
int n = 0;
n=20;
you can simply write
int n = 20;
Your primesArr variable is uninitialized.
Declaring a pointer as
int *ptr;
Just declares a pointer to an int. However, the pointer itself does not point to anything. Much like declaring
int val;
does not initialize val. Therefore, you'll need to allocate memory for your primesArr pointer to point to (with new or on the stack like int primesArr[N] where N is some large number.
However, since you don't know how many primes you'll get a priori from your genPrimes function and you haven't said that STL is out of the question, I'd consider using a std::vector<int> as the input to your genPrimes function:
int genPrimes(int seed, std::vector<int>& test)
And, from within the function, you could do:
test.push_back(k)