Issues with Sieve of Eratosthenes - c++

I picked up "Programming Principles and Practice using C++", and was doing an early problem involving the Sieve of Eratosthenes, and I'm having unexpected output, but I cannot pin down exactly what the problem is. Here is my code:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> prime;
std::vector<int> nonPrime;
int multiple = 0;
for(int i = 2; i < 101; i++) //initialized to first prime number, i will
// be the variable that should contain prime numbers
{
for(int j = 0; j < nonPrime.size(); j++) //checks i against
// vector to see if
// marked as nonPrime
{
if(i == nonPrime[j])
{
goto outer;//jumps to next iteration if number
// is on the list
}
}
prime.push_back(i); //adds value of i to Prime vector if it
//passes test
for(int j = i; multiple < 101; j++) //This loop is where the
// sieve bit comes in
{
multiple = i * j;
nonPrime.push_back(multiple);
}
outer:
;
}
for(int i = 0; i < prime.size(); i++)
{
std::cout << prime[i] << std::endl;
}
return 0;
}
The question only currently asks me to find prime numbers up to 100 utilizing this method. I also tried using this current 'goto' method of skipping out of a double loop under certain conditions, and I also tried using a Boolean flag with an if statement right after the check loop and simply used the "continue;" statement and neither had any effect.
(Honestly I figured since people say goto was evil perhaps it had consequences that I hadn't foreseen, which is why I tried to switch it out) but the problem doesn't call for me to use modular functions, so I assume it wants me to solve it all in main, ergo my problem of utilizing nested loops in main. Oh, and to further specify my output issues, it seems like it only adds multiples of 2 to the nonPrime vector, but everything else checks out as passing the test (e.g 9).
Can someone help me understand where I went wrong?

Given that this is not a good way to implement a Sieve of Eratosthenes, I'll point out some changes to your code to make it at least output the correct sequence.
Please also note that the indentation you choose is a bit misleading, after the first inner loop.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> prime;
std::vector<int> nonPrime;
int multiple = 0;
for(int i = 2; i < 101; i++)
{
// you can use a flag, but note that usually it could be more
// efficiently implemented with a vector of bools. Try it yourself
bool is_prime = true;
for(int j = 0; j < nonPrime.size(); j++)
{
if(i == nonPrime[j])
{
is_prime = false;
break;
}
}
if ( is_prime )
{
prime.push_back(i);
// You tested 'multiple' before initializing it for every
// new prime value
for(multiple = i; multiple < 101; multiple += i)
{
nonPrime.push_back(multiple);
}
}
}
for(int i = 0; i < prime.size(); i++)
{
std::cout << prime[i] << std::endl;
}
return 0;
}

Related

How to fix problem with array overload in while loop

I'm trying to fix a SIGSEGV error in my program. I am not able to locate the site of error. The program compiles successfully in Xcode but does not provide me the results.
The goal of the program is to check whether the same element occurs in three separate arrays and return the element if it is more than 2 arrays.
#include <iostream>
using namespace std;
int main()
{
int i = 0 ,j = 0,k = 0;
int a[5]={23,30,42,57,90};
int b[6]={21,23,35,57,90,92};
int c[5]={21,23,30,57,90};
while(i< 5 or j< 6 or k< 5)
{
int current_a = 0;
int current_b = 0;
int current_c = 0;
{ if (i<5) {
current_a = a[i];
} else
{
;;
}
if (j<6)
{
current_b = b[j];
} else
{
;;
}
if (k<5)
{
current_c= c[k];
} else
{
;;
}
}
int minvalue = min((current_a,current_b),current_c);
int countoo = 0;
if (minvalue==current_a)
{
countoo += 1;
i++;
}
if (minvalue==current_b)
{
countoo +=1;
j++;
}
if (minvalue==current_c)
{
countoo += 1;
k++;
}
if (countoo >=2)
{
cout<< minvalue;
}
}
}
I am not getting any output for the code.
This is surely not doing what you want
int minvalue = min((current_a,current_b),current_c);
If min() is defined meaningfully (you really should provide an MCVE for a question like this), you want
int minvalue = min(min(current_a,current_b),current_c);
This will result in the minimum of the minimum of (a and b) and c, i.e. the minimum of all three, instead of the minimum of b and c. The comma operator , is important to understand this.
This seems to be a flag/counter to make a note across loop executions or count something
int countoo = 0;
It can however not work if you define the variable inside the loop.
You need to move that line BEFORE the while.
With this line you do not prevent the indexes to leave the size of the arrays,
that is very likely the source for the segfault.
while(i< 5 or j< 6 or k< 5)
In order to prevent segfaults, make sure that ALL indexes stay small enough,
instead of only at least one.
while(i< 5 && j< 6 && k< 5)
(By the way I initially seriously doubted that or can compile. I thought
with a macro for or it could, but I do not see that. It could be a new operator in a recent C++ standard update which I missed...
And it turns out that it is the case. I learned something here.)
This should fix the segfault.
To achieve the goal of the code I think you need to spend some additional effort on the algorithm. I do not see the code being related to the goal.

C++ Printing Odd numbers instead of Prime Numbers

I have been working on an assignment question for days and cannot seem to get the correct output (I've tried so many things!) The question is:
Write a program that uses two nested for loops and the modulus operator (%) to detect and print the prime numbers from 1 to 10,000.
I have been doing from 1 to 10 as a small test to ensure its working. I am getting 2,3,5,7,9 as my output, so I know something is wrong. When I increase the number from 10 to 20 it is printing 2 plus all odd numbers. I am including my code below. Thanks!!
int main() {
for (int i=2; i <=10; i++){
for (int j=2; j<=i; j++){
if (i%j==0 && j!=i) {
break;
}
else {
cout<< i <<endl;
break;
}
}
}
}
In addition to Sumit Jindal's answer inner for loop can be done by this way as well:
for(int j=2; j*j<=i ; j++)
If we think about every (x,y) ordered pair that satisfies x*y = i, maximum value of x can be square root of i.
The problem lies in the if-else branch. Your inner loop will be run exactly once because it will break out of the inner loop as a result of your if else branch.
When you first enter the inner loop the value of j is 2. Your condition will test if variable i is divisible by 2. If it is it breaks. Other wise (your else branch) will print the value of i and breaks out.
Hence printing odd numbers.
Break out of the inner loop and check whether j equals i in outer loop. You have to make j available for outer loop.
Your print statement is within the inner loop, and it should not be - it's only a prime if you run all the way through the inner loop without finding a divisor.
As a second point, you only need to check for divisors up to the square root of i, not all the way up to i.
You are breaking the inner loop after the first iteration itself, which is checking if the number(ie i) is different from j and is divisible by 2 or not (since j=2 for the first iteration)
I am getting 2,3,5,7,9 as my output
This is because every odd number fails the if and is printed in else condition
A minor correction in your code, adding a flag. Also you don't need to run the inner loop i times, infact only i/2 times is sufficient. This is simple mathematics, but will save significant number of CPU cycles (~5000 iterations lesser in your case)
#include <iostream>
int main()
{
int n = 10;
for(int i=2; i<=n; i++){
bool isPrime = true;
for(int j=2; j<=i/2; j++){
if(i!=j && i%j==0){
isPrime = false;
break;
}
}
if(isPrime)
std::cout << i << " ";
}
return 0;
}
Another version, if you don't mind output in reverse order.
int n = 10;
for (int i = n; i > 1; --i)
{
int factorCount = 0;
for (int j = 2; j <= n; ++j)
{
if (i % j == 0)
factorCount++;
if (factorCount > 1)
break;
}
if (factorCount == 1)
cout << i << endl;
}
int main() {
for (int i = 2; i <= 100; i++) {
for (int j = 2; j < i; j++) {
if (i%j == 0)
break;
if (j==i-1) // means has never run previous if blog
cout << i << endl;
}
}
return 0;
}

Sieve of Eratosthenes C++ Infinite Loop

So, I've been working through a problem in Bjarne Stroustrup's Programming: Principles and Practices Using C++ for my own benefit, and this problem has stumped me for a couple of days now.
I'm supposed to implement the classic Sieve of Eratosthenes algorithm with the tools learned by chapter 4 (that's not a lot) and this is what I have so far:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int p = 2;
int n = 0;
vector<int> nums{ 1, 1 };
cout << "Enter an integer greater than 1:\n";
cin >> n;
for (int i = 2; i <= n; ++i)
nums.push_back(0);
while (p < sqrt(n))
{
for (int i = 2; (i*p) <= n; ++i)
{
nums[i*p] = 1;
}
for (int i = (p+1); i <= n; ++i)
{
if (nums[i] == 0)
{
p = i;
break;
}
}
}
for (int i = 0; i <= n; ++i)
{
if (nums[i] == 0)
cout << i << '\n';
}
return 0;
}
This code is SOOO close to working but no cigar. It only prints the prime numbers after and including 5, it does not print 2 or 3. I know that the problem is due to the fact that my marking loop is marking nums[2] and nums[3], so I tried to add the following line of code to insure that 2 and 3 were unmarked, because they were used as the p starting values:
nums[p] = 0;
I put that line in-between the two for-loops nested within the while-loop. I have no idea how, but that somehow causes an infinite loop that I've tried for hours to fix. I'm really at my wit's end here.
NOTE: I've been testing this with n = 23.
So, after fixing your first loop starting point, the issue is the next loop.
Because the next loop always starts at 0 and looks for the next prime number, it is going to always find 2, and that will cause an infinite loop.
To solve this issue, start your search for the next prime, from the previous value:
for(int i = p + 1; i <= n; ++i)

Prime number finder cannot find prime, stops after 7

So I made a simple prime number finder for the numbers between 3 and 200. It has to use a boolean variable, just fyi. No errors occur. output is:
The prime numbers between 3 and 200 are:
3
5
7
Why does it not keep going? I have drawn it out on paper time and again and cannot find my logic error.
In addition; I wrote this out by hand because I do not know how to get the contents of my file. It exists on a remote host which I do not have root access to. Is there a better way to copy the file?
#include <iostream>
using namespace std;
int main()
{
int count=0;
cout<<"The prime numbers between 3 and 200 are: "<<endl;
for (int i=3;i<=200;i++)
{
for (int j=2;j<i;j++)
{
bool ptest=i%j;
if (!ptest)
{
break;
}
else if (ptest)
{
count=count+1;
if (count==(i-2))
cout<<i<<endl;
}
}
}
}
You forgot to set count back to 0 after using it in the j loop. Move the line:
int count = 0;
to be inside the first for loop. Then your program works correctly (although as msw indicated, it is not the most efficient technique!)
Some things to consider:
You don't need to consider any even numbers in your code.
You have some logic errors in your code. The value of count needs to be checked after the second for loop. count needs to be reset before the second for loop begins.
You can stop immediately after you find the number is not prime in the inner loop instead of continuing on. You can just use a flag isPrime instead of counting.
Here's a version of the code that works for me:
#include <iostream>
using namespace std;
int main()
{
cout << "The prime numbers between 3 and 200 are: " <<endl;
for (int i=3; i <= 200; i += 2) {
bool isPrime = true;
for (int j=3; j < i; j += 2) {
if (i % j == 0) {
isPrime = false;
break;
}
}
if (isPrime)
{
cout << i << endl;
}
}
}
You don't have to loop till j reach i, instead you can check if j < sqrt(i) ,i.e. write in the second for loop: for (int j=3; j*j<=i; j+=2)

Can I use break to exit multiple nested 'for' loops?

Is it possible to use the break function to exit several nested for loops?
If so, how would you go about doing this? Can you also control how many loops the break exits?
No, don't spoil it with a break. This is the last remaining stronghold for the use of goto.
AFAIK, C++ doesn't support naming loops, like Java and other languages do. You can use a goto, or create a flag value that you use. At the end of each loop check the flag value. If it is set to true, then you can break out of that iteration.
Just to add an explicit answer using lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Of course this pattern has a certain limitations and obviously C++11 only but I think it's quite useful.
Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.
Of course, this brings up the other argument of whether you should ever explicitly return from a function anywhere other than at the end.
break will exit only the innermost loop containing it.
You can use goto to break out of any number of loops.
Of course goto is often Considered Harmful.
is it proper to use the break function[...]?
Using break and goto can make it more difficult to reason about the correctness of a program. See here for a discussion on this: Dijkstra was not insane.
How about this?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Although this answear was already presented, i think a good approach is to do the following:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
A code example using goto and a label to break out of a nested loop:
for (;;)
for (;;)
goto theEnd;
theEnd:
One nice way to break out of several nested loops is to refactor your code into a function:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
I know this is an old thread but I feel this really needs saying and don't have anywhere else to say it. For everybody here, use goto. I just used it.
Like almost everything, goto is not 100% either/xor "bad" or "good". There are at least two uses where I'd say that if you use a goto for them - and don't use it for anything else - you should not only be 100% okay, but your program will be even more readable than without it, as it makes your intention that much clearer (there are ways to avoid it, but I've found all of them to be much clunkier):
Breaking out of nested loops, and
Error handling (i.e. to jump to a cleanup routine at the end of a function in order to return a failure code and deallocate memory.).
Instead of just dogmatically accepting rules like "so-so is 'evil'", understand why that sentiment is claimed, and follow the "why", not the letter of the sentiment. Not knowing this got me in a lot of trouble, too, to the point I'd say calling things dogmatically "evil" can be more harmful than the thing itself. At worst, you just get bad code - and then you know you weren't using it right so long as you heard to be wary, but if you are wracking yourself trying to satisfy the dogmatism, I'd say that's worse.
Why "goto" is called "evil" is because you should never use it to replace ordinary ifs, fors, and whiles. And why that? Try it, try using "goto" instead of ordinary control logic statements, all the time, then try writing the same code again with the control logic, and tell me which one looks nicer and more understandable, and which one looks more like a mess. There you go. (Bonus: try and add a new feature now to the goto-only code.) That's why it's "evil", with suitable scope qualification around the "evil". Using it to short-circuit the shortcomings of C's "break" command is not a problematic usage, so long as you make it clear from the code what your goto is supposed to accomplish (e.g. using a label like "nestedBreak" or something). Breaking out of a nested loop is very natural.
(Or to put it more simply: Use goto to break out of the loop. I'd say that's even preferable. Don't use goto to create the loop. That's "evil".)
And how do you know if you're being dogmatic? If following an "xyz is evil" rule leads your code to be less understandable because you're contorting yourself trying to get around it (such as by adding extra conditionals on each loop, or some flag variable, or some other trick like that), then you're quite likely being dogmatic.
There's no substitute for learning good thinking habits, moreso than good coding habits. The former are prior to the latter and the latter will often follow once the former are adopted. The problem is, however, that far too often I find, the latter are not explicated enough. Too many simply say "this is bad" and "this needs more thought" without saying what to think, what to think about, and why. And that's a big shame.
(FWIW, in C++, the need to break out of nested loops still exists, but the need for error codes does not: in that case, always use exceptions to handle error codes, never return them unless it's going to be so frequent that the exception throw and catch will be causing a performance problem, e.g. in a tight loop in a high demand server code, perhaps [some may say that 'exceptions' should be 'used rarely' but that's another part of ill-thought-out dogmatism: no, at least in my experience after bucking that dogma I find they make things much clearer - just don't abuse them to do something other than error handling, like using them as control flow; effectively the same as with "goto". If you use them all and only for error handling, that's what they're there for.].)
goto can be very helpful for breaking nested loops
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
I'm not sure if it's worth it, but you can emulate Java's named loops with a few simple macros:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Example usage:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Another example:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.
from msdn.
I do think a goto is valid in this circumstance:
To simulate a break/continue, you'd want:
Break
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
Continue
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
Break any number of loops by just one bool variable see below :
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
In this code we break; all the loops.
Other languages such as PHP accept a parameter for break (i.e. break 2;) to specify the amount of nested loop levels you want to break out of, C++ however doesn't. You will have to work it out by using a boolean that you set to false prior to the loop, set to true in the loop if you want to break, plus a conditional break after the nested loop, checking if the boolean was set to true and break if yes.
I know this is old post . But I would suggest a bit logical and simpler answer.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
bool found = false;
for(int i=0; i < m; ++i){
for(int j=0; j < n; ++j)
if(grid[i][j] == '*'){
q.push(make_pair(i,j));
found = true;
break;
}
if(found)
break;
}
My suggestion is use a check variable to break a desired loop. The result code may not be so pleasant.
You can use preprocessors in order to make desired breaking under the hood. This approach can hides ugly codes and extra complexity.
For example, I created my custom break mechanism as follow:
Wanted code:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
breakToLevel = 0;
}
if (breakToLevel < 3) {
break;
}
}
if (breakToLevel < 2) {
break;
}
}
if (breakToLevel < 1) {
break;
}
}
Defined macros:
#define BREAK_TO(L) breakToLevel = (L);
#define CHECK_BREAK(L) if (breakToLevel < (L)) break;
and result:
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
for (int k = 0; k < 100; k++) {
//do something
if (desiredCondition) {
BREAK_TO(0)
}
CHECK_BREAK(3)
}
CHECK_BREAK(2)
}
CHECK_BREAK(1)
}
while (i<n) {
bool shouldBreakOuter = false;
for (int j=i + 1; j<n; ++j) {
if (someCondition) {
shouldBreakOuter = true;
}
}
if (shouldBreakOuter == true)
break;
}
you can use "goto" to leave nested loops
below is my original code including "goto"
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
goto fail;
}
}
cout << sum << endl;
fail:
}
return 0;
}
however, I could avoid "goto" by adding a function "calculate"
void calculate(const string &str)
{
int sum = 0;
for (auto ch : str)
{
if (ch <= 'z' && ch >= 'a')
sum += (ch - 'a' + 1);
else if (ch >= 'A' && ch <= 'Z')
sum += (ch - 'A' + 1);
else
{
cout << "Fail" << endl;
return;
}
}
cout << sum << endl;
}
int main()
{
string str;
while (cin >> str)
{
if (str == "0")
break;
calculate(str);
}
return 0;
}
You can use try...catch.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
If you have to break out of several loops at once, it is often an exception anyways.
Breaking out of a for-loop is a little strange to me, since the semantics of a for-loop typically indicate that it will execute a specified number of times. However, it's not bad in all cases; if you're searching for something in a collection and want to break after you find it, it's useful. Breaking out of nested loops, however, isn't possible in C++; it is in other languages through the use of a labeled break. You can use a label and a goto, but that might give you heartburn at night..? Seems like the best option though.