Stroustrup Chapter4 Exercise 11 - c++

I am working through Programming: Principles and Practice Using C++ and I am on chapter 4, exercise 11. The question wants you to write a program that detects all primes between 1 ans 100. This is what I have so far
//This program finds the prime numbers between 1 and 100
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>primes;
bool ptest(int y)
{
int p=0, x=0;
for (x==0; x<primes.size(); ++p)
{
if (y%primes[x]==0)
{
return false;
}
return true;
}
}
int main()
{
int i=3;
primes.push_back(2);
vector<int>comp;
for (i==3; i<=100; ++i)
{
if (ptest(i)==true)
{
primes.push_back(i);
}
}
for (int x:primes)
{
cout << x << " ";
}
}
For some reason, the program prints 2, followed by all of the odds from 3-100. I am not sure what I am missing here.
EDIT: Question has been answered. Thep was from a previous try that I forgot to change. The major mistake here was me not knowing that the return true value belonged outside of the loop.
Thanks

Errors:
Your return true; is in wrong position. It should be after the loop.
x have to be updated in the iterations.
Warnings:
The first expression x==0 in for loop is meaningless.
p is meaningless because its value is not used.
Try this:
bool ptest(int y)
{
for (int x=0; x<primes.size(); ++x)
{
if (y%primes[x]==0)
{
return false;
}
}
return true;
}

Related

How to check if a number is in a vector, and if not, then to return -1?

This is pretty easy if I can import <algorithm> or any other things at the top, but I just started using C++ and my professor asked us to use only loops and conditionals for this problem.
The problem itself is to give a vector v and an int seek to a function. A loop runs through the vector to find the index of the first location of the number. If it can be found, then return the index of where the number is, if not then return -1.
I got the first part down, but now I am having an issue with the second part.
#include <iostream>
#include "vectorutils.h"
#include <vector>
using namespace std;
//endl = new line
int main() {
cout << find({1, 2, 3, 4, 5, 6, 7, 8}, 28) << endl;
}
int find(const std::vector<int>& v, int seek) {
int ind = 1;
for (int i = 0; i < v.size(); i++) {
if (seek == v[i]) {
return i;
}
else {
return -1;
}
}
You have the return -1; statement in the wrong place. It needs to be after the loop exits, not inside the loop. For example:
int find(const std::vector<int>& v, int seek) {
for (int i = 0; i < v.size(); i++) {
if (seek == v[i]) {
return i;
}
// else {
// return -1;
// }
}
return -1; // <-- moved down here!
}
In your original code (if it could compile, which it doesn't), the logic is wrong. If the vector is empty then you return nothing at all (which is undefined behavior), and if the 1st element does not match the number then you return -1 immediately without checking the remaining elements at all.
The above change fixes both of those issues.

sieve upto 2 billion gives segmentation fault

I am using this program to check a number if prime or not.
Use algorithm - Sieve :
#include<bits/stdc++.h>
//#define _max 2000000001
#define _max 20000001
using namespace std;
bool sieve[_max];
void init()
{
memset(sieve,true,sizeof(sieve));
sieve[0]=sieve[1]=false;
for(int i=2;i<_max;i+=2)
{
sieve[i]=false;
}
}
void go_sieve(int n)
{
n++;
for(int i=3;i<n;i+=2)
{
if(sieve[i]==false)
continue;
for(int j=2*i;j<n;j+=i)
sieve[j]=false;
}
}
void print(int n)
{
n++;
printf("-------------\n");
for(int i=0;i<n;i++)
{
if(sieve[i])
cout << i << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
go_sieve(x);
//print(x);
if(sieve[x])
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Now it works upto 2e7 and pretty smoothly, but I want to check upto 2e9, if I change my _max to 2000000001 it gives me segmentation error and exits with an error code.
How can I resolve this problem ?
I have tried a new approach with set :
#include<bits/stdc++.h>
//#define _max 200001
//#define _max 20000001
#define _max 2000000001
using namespace std;
set<int>prime;
set<int>nprime;
void init()
{
prime.insert(2);
}
void go_sieve()
{
for(int i=3;i<_max;i+=2)
{
if(prime.find(i)==prime.end() && nprime.find(i)==nprime.end())
{
prime.insert(i);
//cout << i << endl;
for(int j=2*i;j<_max;j+=i)
nprime.insert(j);
}
if(nprime.find(i)!=nprime.end())
nprime.erase(nprime.find(i));
}
}
void print()
{
set<int> ::iterator itt;
printf("-------------\n");
for(itt=prime.begin();itt!=prime.end();itt++)
{
cout << *itt << " ";
}
printf("\n-------------\n");
}
int main()
{
init();
go_sieve();
//print();
int n;
scanf("%d",&n);
while(n--)
{
int x;
scanf("%d",&x);
if(prime.find(x)!=prime.end())
printf("Prime\n");
else
printf("Not prime\n");
}
return 0;
}
Target is to execute it within 512MB~1GB memory.
If you want to enumerate large ranges of prime numbers, you should use a segmented Sieve of Eratosthenes; it will be faster (due to caching effects) and use less memory.
If you only want to determine if one number is prime, or a few numbers, sieving is a horrible way to do it. Sieving should only be used when you are interested in an entire range of numbers. For n up to a billion, trial division is simple and probably fast enough. For larger numbers, a Miller-Rabin test or Baillie-Wagstaff test is probably better.
I can't reproduce this on my system. My guess is that this has to do with a system dependant limitation.
You declare sieve as a global array (static storage duration) and it's huge (i.e. 2000000001 * sizeof(bool) - could be 2-8G depending on sizeof bool). Maybe your system can't handle that.
Instead of a global array, try using dynamic allocation:
// bool sieve[_max]; comment out this
bool* sieve = NULL;
...
...
int main()
{
sieve = (bool*)malloc(_max * sizeof *sieve);
if (sieve == NULL)
{
// out of memory
exit(1);
}
...
That said:
Your code is C++ but your style is more C like.
In C++ you would probably use a std::vector instead. That would make everything much easier.
BTW: Also avoid globals. Instead define the vector (or dynamic array) in main and pass it by-reference to the functions.
You probably hit some memory limit on your system which causes the segmentation fault.
However, you don't need such a big array. Using Sieve of Eratosthenes, you need to calculate numbers up to x. Instead of an array you can use std::vector and increase its size as you calculate more numbers. This should allow you to calculate some numbers, but with large numbers you will hit the memory limit again.
You could also use some algorithm which requires you to store fewer numbers. To determine whether x is prime, you only need to compare against prime numbers that are smaller than the square root of x. You don't have to store numbers that are not primes. With x = 1e10, you would only need to store 5e8 numbers.
Here is some example with vector (probably not optimal):
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
std::vector<int> primes = {2};
void calculate(int x) {
const int largest_prime = primes.back();
if (largest_prime >= x) {
// Already calculated
return;
}
for (size_t i = largest_prime + 1; i <= x; i++) {
bool not_prime = false;
for (size_t j = 0; j < primes.size(); j++) {
if (i % primes[j] == 0) {
not_prime = true;
break;
}
}
if (!not_prime) {
primes.push_back(i);
}
}
}
bool check(int x) {
calculate(x);
return std::find(primes.begin(), primes.end(), x) != primes.end();
}
int main() {
std::cout << check(15) << std::endl;
std::cout << check(256699) << std::endl;
}

Can someone help me with rectifying the output of this "Prime Numbers below 100" code?

This Question has been answered
So basically, I just wrote down a code to display all the prime numbers below 100. This is the code:
#include <iostream>
using namespace std;
int main()
{
int n=2,i;
cout<<"All Prime numbers below 100 are : \n";
while(n<=100)
{
for(i=2; i<n/2; i++)
{
if (n%i==0)
{
goto restart;
}
else
{
cout<<n<<"\t";
}
}
restart:
n++;
}
return 0;
}
But instead of the output being 2 3 5 7 11 ..... it comes out as:
All prime numbers below 100 are:
7 9 11 11 11 13 13 13 13 15 15 and so on ...
I just want the output to display all prime numbers starting from 2 to 97 without repetitions. thank you.
/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/--/-/-/-/-
I got out of the problem with a slight modification.
#include<iostream>
using namespace std;
int main()
{
int n=2, i;
while(n<=100)
{
for(i=2; i<=n/2; i++)
{
if(n%i==0)
{
goto label;
}
}
cout<<n<<", ";
label:
n++;
}
return 0;
}
Thank you to everyone for your valuable time. (And the reason why I use such beginner type codes is I've just started out on C++ like a week ago. I have so much more codes (like bool, isPrime, etc.) to learn.)
Keeping Cranking 'em codes, fellow coders :D
There is an obvious error in your algorithm. You might be able to find it using a debugger, but I think that a better way would be for you to learn about extracting a function. What you want your main function to do, is exactly: if n is prime: output n. So you should write it that way:
int main()
{
for (int i = 0; i < 100; ++i)
if (is_prime(i))
std::cout << i << std::endl;
}
Of course for that to work you'll need to define the function is_prime:
bool is_prime (int n) {
for (int i = 2; i * i <= n; ++i)
if (n % i == 0)
return false;
return true;
}
Note also that there is no need to check if n is divisible by numbers greater then it's square root. If there are no divisors up to the square root, the next possible divisor is n itself.
As others mentioned, that's not the optimal algorithm to solve this problem, but for small values it's definetely good enough.
Your answer is OK but has two critical errors. Firstly, you output n for each modulo you check. You should only output n if all the modulo checks fail. Also, your boundary condition isn't quite right - it should be <=. Working code with minimal changes would be:
#include <iostream>
using namespace std;
int main()
{
int n=2,i;
cout<<"All Prime numbers below 100 are : \n";
while(n<=100)
{
for(i=2; i<=n/2; i++)
{
if (n%i==0)
{
goto restart;
}
}
cout<<n<<"\t";
restart:
n++;
}
return 0;
}
If you wanted to make slightly cleaner code then dont use goto, use a double for loop and a break. Also your boundary condition for i should be i*i<=n as thats a tighter bound. So something like:
#include <iostream>
int main()
{
cout<<"All Prime numbers below 100 are : \n";
for(int n=2; n<100; ++n)
{
bool isPrime = true;
for(int i=2; i*i<=n; i++)
{
if (n%i==0)
{
isPrime = false;
break;
}
}
if(isPrime)
std::cout<<n<<"\t";
}
}
You are trying to check if each number is prime. Therefor you have to check if it is dividable by a smaller number.
A more efficient way to find all prime numbers up to a maximal number is the Sieve of Erathosthenes:
#include <iostream>
#include <vector>
int main() {
const unsigned int maxNum(100);
std::vector<bool> prime(maxNum, true);
for (unsigned int i(2); i*i < maxNum; ++i) {
if (!prime[i]) continue;
for (unsigned int j(2*i); j < maxNum; j += i) {
prime[j] = false;
}
}
for (unsigned int i(2); i < maxNum; ++i) {
if (prime[i]) std::cout << i << std::endl;
}
return 0;
}
A list of all numbers is created. Each multiple of of each number is removed from this list.

How to make a while loop till there is something to be readen c++

I know that you probably gona again vote me down, I really don't understand this but im really stuck at something and cant figure it out , there is no such information anywhere in the web , neither in my book for the course, so I have this assignment where I need make 2 sums of containers where the difference between 2 sums is the lowest , so the program is done is working perfectly calculated everything however , in my assignment:
The user enter on one row unkwonw length numbers so after that I do all kind of sums between them and find the one with lowest difference between.
Ok but the way I wrote the code I use one while(true) so that to work with infinity testcases(as from assignment) and in this while(true) I have another while(cin>>(SOMEINT)) loop and push it back in a vector , and after it reads new line it just break the wile and continue with the calculation.
However in our test software this one give runtime error since after finding some cases then it start print infinity 0 0 since there is nothing to enter but the while(true) just continues.
I mean I just want to make it that way that the while is till user enters something , for instance you enter 30 50 90 it will return 80 90 , then wiat for another entry and so on.
CODE:
#include <iostream>
#include <string>
#include<vector>
#include <sstream>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include <climits>
using namespace std;
const int length = 17000;
int power(int x){
int sum =2;
for(int i = 0;i<x;i++) {
sum *= 2;
}
return sum;
}
bool ison(int i,int x)
{
if((i>>x) & 1)return true;
return false;
}
int main()
{
while(true){
vector<int> Vec;
int cur = 0;
while (cin >> cur) {
Vec.push_back(cur);
if (cin.get() == '\n') {
break;
}
}
int * sumOfarr1 = new int[length];
int * sumOfarr2 = new int[length];
for(int i = 0; i<length;i++){
sumOfarr1[i] = 0;
}
for(int i = 0; i<length;i++){
sumOfarr2[i] = 0;
}
int index=0;
for(int i=1;i<length;i++)
{
for(int j=0;j<Vec.size();j++)
{
if(ison(i,j))
{
sumOfarr1[index]+=Vec[j];
}
else
{
sumOfarr2[index]+=Vec[j];
}
}index++;
}
int ans=INT_MAX;
int ii;
for(int i=0;i<index;i++)
{
if(abs(sumOfarr1[i]-sumOfarr2[i])<ans)
{
ii=i;
ans=abs(sumOfarr1[i]-sumOfarr2[i]);
}
}
if(sumOfarr1[ii]<sumOfarr2[ii]){
cout << sumOfarr1[ii] << " " << sumOfarr2[ii];
}
else{
cout << sumOfarr2[ii] << " " << sumOfarr1[ii];
}
cout << endl;
delete[] sumOfarr1;
delete[] sumOfarr2;
Vec.clear();
}
return 0;
}
Yes I found the solution just using getline and stringstream.
aka this
vector<int> Vec;
string line;
while(getline( cin, line ))
{
istringstream iss( line );
int number;
while( iss >> number )
Vec.push_back(number);
}

C++ Vector Elements Count

In C++, using the vector header, how do I find the number of elements?
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int primer(int max);
int main()
{
system("pause");
return 0;
primer(1000);
}
int primer(int max){
vector<int> a;
a[1]=2;
for (int i=2;i<=max;i++){
bool prime=true;
for (int ii=1;ii<=#a;ii++) {
if i/a[ii]==math.floor(i/a[ii]) {
prime=false;
}
}
if prime==true {
a[#a+1]=i;
}
}
for (i=1;i<=#a;i++) {
cout << a[i]);
}
}
}
I originally wrote the code
for lua, and this is my attempt to translate it to C++. I would appreciate specifics, for example, a specific replacement for a bad line. I tried to replace #a with a.size, but it didn't work.
Revised:
#include <iostream>
#include <cmath>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int primer(int max);
int main()
{
primer(5);
system("pause");
return 0;
}
int primer(int max){
vector<int> a;
a[1]=2;
for (int i=2;i<=max;i++){
bool prime=true;
for (int ii=0;ii<a.size();ii++) {
if (i/a[ii]==floor(i/a[ii])) {
prime=false;
}
}
if (prime==true) {
a.push_back(i);
}
}
for (int iii=0;iii<=a.size();iii++) {
cout << a[iii] << endl;
}
}
It crashes without running. For what reason is this?
a.size().
I would recommend using some sort of reference material, e.g. http://cplusplus.com/reference/stl/vector/.
To answer your immediate question:
a.size(); // use size as a function
But there are several other things wrong with your code:
vector<int> a;
a[1]=2;
Ordinarily you need to set the size of a beforehand, since C++ must allocate space for it. You can use push_back() though, which will incrementally add space as needed.
Also, C++ arrays start counting at 0:
for (int ii=1;ii<=#a;ii++) {
This should be
ii = 0
And since arrays start at 0, they end at size() - 1, not size().
for( int ii = 0; ii < a.size(); ++ii )
C and C++ array indexes start at zero and end at size-1, so you need to compare less-than, not less-than-or-equal-to. vector follows the same rule.
Another obvious problem that needs pointing out:
int main()
{
system("pause");
return 0;
primer(1000);
}
Your function is never going to be called. Your app will exit when main returns.
a[#a+1]=i;
changed to use size() becomes:
a[ a.size() + 1 ] = i;
This is syntactically correct but guaranteed wrong. It should be:
a.push_back(i);
Read the API referenced by Oli.