Is using goto a legitimate way to break out of two loops? - c++

I am solving problem 9 on the Project Euler. In my solution I use a "goto" statement to break out of two for loops. The Problem is the following:
A Pythagorean triplet is a set of three natural numbers, a b c, for which,
a^2 + b^2 = c^2
For example, 3^2 + 4^2 = 9 + 16 = 25 = 52.
There exists exactly one Pythagorean triplet for which a + b + c = 1000.
Find the product abc.
My solution is in c++:
int a,b,c;
const int sum = 1000;
int result = -1;
for (a = 1; a<sum; a++){
for (b = 1; b < sum; b++){
c = sum-a-b;
if (a*a+b*b == c*c){
result = a*b*c;
goto found;
}
}
}
found:
std::cout << "a:" << a << std::endl;
std::cout << "b:" << b << std::endl;
std::cout << "c:" << c << std::endl;
std::cout <<"Result:" << result << std::endl;
Since "goto" statements are not very popular among c++ programmers, i would like to know, if this could be considered a reasonable use of "goto". Or if there is a better solution for the problem that doesn't need "goto". By that I don't mean a solution which just avoids "goto", but which avoids "goto" in a way that improves the algorithm.

return is a "structured" goto which many programmers find more acceptable! So:
static int findit(int sum, int* pa, int* pb, int* pc)
{
for (int a = 1; a<sum; a++) {
for (int b = 1; b < sum; b++) {
int c = sum-a-b;
if (a*a+b*b == c*c) {
*pa = a; *pb = b; *pc = c;
return a*b*c;
}
}
return -1;
}
int main() {
int a, b, c;
const int sum = 1000;
int result = findit(sum, &a, &b, &c);
if (result == -1) {
std::cout << "No result!" << std::endl;
return 1;
}
std::cout << "a:" << a << std::endl;
std::cout << "b:" << b << std::endl;
std::cout << "c:" << c << std::endl;
std::cout <<"Result:" << result << std::endl;
return 0;
}

In my opinion it's fine to use goto in a situation like this.
Btw, the condescending preaching against goto usually comes from people who just parrot what they heard others say or read somewhere..

See this question about breaking out of 2 loops. There are much better answers provided than using a goto.
The best answer provided is to place your second loop into a function, and call that function from inside your first loop.
code copied from mquander's response
public bool CheckWhatever(int whateverIndex)
{
for(int j = 0; j < height; j++)
{
if(whatever[whateverIndex][j]) return false;
}
return true;
}
public void DoubleLoop()
{
for(int i = 0; i < width; i++)
{
if(!CheckWhatever(i)) break;
}
}
Though I do feel that using a goto in this case isn't quite as bad as killing kittens. But it's close.

I can't think of a better alternative. But one alternative not using goto would be modifying the first for-loop:
for (a = 1; a<sum && result == -1; a++){
Then break out of the second for-loop. That will work assuming the result will never be -1 after the second for-loop has been broken by break.

You could declare a bool found = false at the top and then add && !found to your for loop conditionals (after a < sum and b < sum) and then set found to true where your current goto is. Then make your output conditional on found being true.

int a,b,c,sum = 1000;
for (a = 1; a<sum; ++a)
for (b = 1; b<sum; ++b){
c = sum-a-b;
if (a*a+b*b == c*c) sum = -a*b*c;
}
printf("a: %d\n",a-1);
printf("b: %d\n",b-1);
printf("c: %d\n",c);
printf("Result: %d\n",-sum);
Also optimized result out.. :P
Anyway i love gotos!

Related

my object::collides(object * o) function always returns true, but doesn't do anything

I have a function that returns a boolean. this function when compiled seems to contain nothing, and will always return true while also skipping over all the calls to cout or cin that i put in it. to see what it's actually doing. What is going on and how do i fix this issue.
In my process of troubleshooting, i have,
used GDB with a breakpoint at object::collides, this resulted in the function being called but not outputting anything to the console
Numbered my objects to and compared what objects the program thinks are colliding to the objects that are colliding. if it passes the proximity test, the program thinks the objects are colliding, evidence that it is always returning true.
tried various other methods to try to figure out what is going on, but all have left my without answers
in object.cpp:
bool object::collides(object * other)
{
std::vector<point> a_pnt = getBounds();
std::vector<point> b_pnt = other->getBounds();
for (int i = 0; i < a_pnt.size(); i++)
{
for (int j = 0; j < b_pnt.size(); j++)
{
point v1 = a_pnt[i];
point v2 = a_pnt[(i+1)%a_pnt.size()];
point v3 = b_pnt[j];
//edit: fixed typo
point v4 = b_pnt[(j+1)%b_pnt.size()];
double num_1 = ((v3.x - v1.x) * -(v4.y - v3.y)) - (-(v4.x - v3.x) * (v3.y - v1.y));
double num_2 = ((v2.x - v1.x) * (v3.y - v1.y)) - ((v3.x - v1.x) * (v2.y - v1.y));
double den =((v2.x - v1.x) * -(v4.y - v3.y)) - (-(v4.x - v3.x) * (v2.y - v1.y));
double frac_1 = num_1 / den;
double frac_2 = num_2 / den;
//debug code start
std::cout << num_1 << "/" << den << "=" << frac_1 << std::endl;
std::cout << num_2 << "/" << den << "=" << frac_2 << std::endl;
std::cout << (frac_1 > 0.0) << " " << (frac_1 < 1.0) << " " << (frac_2 > 0.0) << " " << (frac_2 < 1.0) << std::endl;
std::cout << std::endl;
std::string hahah;
std::cin >> hahah;
//end debug code
//edit: fixed conditional
if((frac_1>0.0)&&(frac_1<1.0)&&(frac_2>0.0)&&(frac_2<1.0));
return true;
}
}
//edit: fixed conditional
return false;
}
in mode.cpp in function mode::step():
for (int i = 0; i<onScreen.size(); i++)
{
object * o1 = onScreen[i];
for(int j = i+1; j<onScreen.size(); j++)
{
object * o2 = onScreen[j];
if(o1->getVectorLength(o2)<50){
std::cout << "Checking collisions for objects " << i << " and " << j << std::endl;
if(o1->collides(o2))
{
std::cout << "somthing collided\n";
}
}
}
}
output:
Checking for Collisions
Checking collisions for objects 0 and 11
somthing collided
Checking collisions for objects 1 and 8
somthing collided
Checking collisions for objects 1 and 18
somthing collided
Checking collisions for objects 1 and 26
somthing collided
Expected results is for the "collides" function to output to the screen or request the input for that string, this will show that it is actually going through that section of code properly. however it doesn't do this. the "collides" function returns true regardless of whether or not the actual intersect section is true or false, while skipping over all of my debug code, as shown in the output.
edits:
fixed the return in collides
fixed a typo
still doesn't work.
does go thought loops with bullet/bullet combinations not bullet/asteroid or asteroid/asteroid
checking getBounds has me scratching my head...
std::vector asteroid::getBounds()
{
//my issue was here, check your functions a bit more closely :P
//wasn't returning a vector with anything in it.
std::vector t;
//now it's
std::vector t = lyrs[0].pnts;
for (int i = 0; i < t.size(); i++)
{
double x = t[i].x+location.x;
double y = t[i].y+location.y;
t[i] = point{x, y, t[i].z};
}
return t;
}
i thought that was implemented properly
The problem occurs on this line:
if((frac_1>0.0)&&(frac_1<1.0)&&(frac_2>0.0)&&(frac_2<1.0)); //This semicolon here
return true;
Putting a semicolon at the end of the if statement basically ends the if statement. What you wrote is equivalent to
if((frac_1>0.0)&&(frac_1<1.0)&&(frac_2>0.0)&&(frac_2<1.0))
{
}
return true;
Fixing it is pretty simple. Just remove the semicolon:
if((frac_1>0.0)&&(frac_1<1.0)&&(frac_2>0.0)&&(frac_2<1.0))
return true;
So my issue was simple, and a bit of a "doh" moment. First the unrealtated issue I had to fix, was a return true, regardless of whether or not my math was actually done correctly, but as this section wasn't being hit, this wasn't the real issue. Thanks for those that noticed it anyway.
Issue one (no if on return true):
In collides.cpp
for (int i = 0; i < a_pnt.size(); i++)
{
for (int j = 0; j < b_pnt.size(); j++)
{
...
return true;
}
}
Fixed to:
for (int i = 0; i < a_pnt.size(); i++)
{
for (int j = 0; j < b_pnt.size(); j++)
{
...
if((frac_1>0.0)&&(frac_1<1.0)&&(frac_2>0.0)&&(frac_2<1.0))
return true;
}
}
The second issue, and the main one, after a suggestion from a commenter, his name is up in the question above, I double checked my getter for the bounding boxes. Low and behold, that was my issue. While at first I discounted his advice, because I thought I had fully implemented that getter, it was my issue and learning valuable lessons is always a good thing.
Issue two(incomplete implementation of GetBounds, resulted in empty vector getting returned.):
in asteroids.cpp:
std::vector asteroid::getBounds()
{
//my issue was here, check your functions a bit more closely :P
//wasn't returning a vector with anything in it.
std::vector<point> t;
//now it's
std::vector<point> t = lyrs[0].pnts;
for (int i = 0; i < t.size(); i++)
{
double x = t[i].x+location.x;
double y = t[i].y+location.y;
t[i] = point{x, y, t[i].z};
}
return t;
}
Lesson to learn: Even when you think you have everything working correctly there are times when you don't and you should check and double check EVERY function you are calling just incase one of those functions you think is working isn't actually working as it should.

Loop not faster despite looping through half as many iterations?

I wrote a program that searches for primes:
#include <iostream>
#include <fstream>
#include <chrono>
typedef std::chrono::high_resolution_clock Clock;
using namespace std;
int main() {
int p;
int x = 1;
int b;
int a[1000000];
bool n = false;
a[0] = 2;
a[1] = 3;
auto t1 = Clock::now();
ofstream outfile;
outfile.open("p.txt");
for (p = 3; p < 7500000; p = p + 2)
{
for (b = 0; b <= x && n == 0; b++)
{
if (p % a[b / 2] == 0)
{
n = true;
}
}
if (n == false)
{
cout << p << endl;
outfile << p << endl;
x++;
a[x] = p;
}
else
{
n = false;
}
}
auto t2 = Clock::now();
std::cout
<< std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count()
<< " nanoseconds" << std::endl;
outfile.close();
}
Initially for the loop increment I had p++, but I changed that to p=p+2 because all primes essentially are odd and even numbers don't need to be checked. Problem is when I benchmarked this, there was no difference in speed between the old and new code. So what is the bottleneck in the process, if checking all the numbers is no different than checking half? And is there a better way to approach this?
Your outer loop skips half the numbers. But your inner loop tests every number twice. So you give up all your gains.
If you don't see that your inner loop does everything twice, consider that a[b/2] is the same when b is 1 as it is when b is 0.
It's this line:
for(b=0; b<=x && n==0; b++)
Once n=true; executes, the b loop exits because of the && n==0 condition. This happens with the very first test: every even number is divisible by two, which is a[0]. So for even numbers (that you include if you use p++ instead of p=p+2) the inner loop is very quick, much quicker than for a typical odd number. This explains why including them makes so little difference.

What is the purpose of the increment statement?

Why are increment statements a thing in for-loops in C++? To me it seems redundant, because you could simply put the increments inside the conditional code. Am I misunderstanding something important here?
To illustrate my question better, I'm including some pseudocode:
What is the difference between ->
for( int a = 10; a < 20; a = a + 1 )
{
cout << a << endl;
}
and
for( int a = 10; a < 20;)
{
a = a + 1
cout << a << endl;
}
It's more than mere convenience sometimes.
These are equivalent:
for (int a = 10; a < 20; a = a + 1) {
cout << a << endl;
}
for (int a = 10; a < 20; ) {
cout << a << endl;
a = a + 1;
}
But, these are not:
// this works ...
for (int a = 10; a < 20; a = a + 1) {
if (blah ...)
continue;
cout << a << endl;
}
// this doesn't
for (int a = 10; a < 20; ) {
if (blah ...)
continue;
cout << a << endl;
a = a + 1;
}
Since you're coming from python, an idiomatic for loop is like a python range, but much more powerful. Your C for loop, expressed in python would be:
for a in range(10,20,1)
It's more idiomatic to express this as:
for (a = 10; a < 20; a += 1)
Because the loop increment is 1, it's even more idiomatic to do this:
for (a = 10; a < 20; ++a)
But, for loops are:
for ([init_stmt]; [test_stmt]; [incr_stmt])
Where any of the *_stmt can be compound:
for (x = 0, y = 0; x < 10; ++x, y += 2)
Convenience.
However, your equivalent code should be:
for (int a = 10; a < 20;)
{
cout << a << endl;
a = a + 1;
}
It runs at the end of the loop body.
[ snips grumbling about quality of now deleted/ edited answers ;-) ]
This:
for (unsigned counter = 1; counter <= 10; ++counter) {
doStuff();
}
is largely equivalent to this:
unsigned counter = 1;
while (counter <= 10) {
doStuff();
++counter;
}
with the notable exception that, in the 1st case, you have the considerable benefit that counter is scoped only to within the for block and automatically goes out-of-scope as soon as it finishes - whereas with the latter, counter must remain in-scope after the loop, where it's potentially useless or even an obstacle.
(tangential: Note that C did not support within-for declaration, or any non-top-of-block declarations, until C99 - but barring extenuating circumstances, anyone not using at least C99 by now is making a questionable choice imho.)
edit: Craig also makes a very good point regarding continue - an oft-forgotten but certainly useful statement. I'm sure there are probably other differences we could conjure up.
for this example:
using namespace std;
int main(int argc, char** argv) {
for( int a = 10; a < 20;)
{
a = a + 1;
cout << a << endl;
}
return 0;
}
the output will be from 11-->20
the first example will be from 10-->19
your are putting the increment part outside the loop and this possible, but notice that the value 10 will not appear, because you are increment before printing the value of a
so in the 2nd example your printing the value and then increment, and at the end of the loop, you are quiting the loop without reaching 20, because the condition get you out the loop
executing code block before increment is the key for you, the for loop increment just after the code block is executed
Well it is not required, it is just for convenience.
In your second code, you made a little mistake which would make the code nonequivalent to the the first one.
Your increment should be at the end of loop in order to be equivalent to the first code
so it should rather be:
for( int a = 10; a < 20;)
{
cout << a << endl;
a = a + 1; //increment at the end of instructions
}
These little errors and also errors like forgetting to include your increment is why it is convenient to include the increment in the for loop.
Or you can use the while loop instead:
while (condition)
{//instructions here;}

C++ Add and Subtracting 100 digits numbers

So what it's supposed to do is be able to take in a const char* str change it to an int then have it be converted back into a string for the output. But it is also supposed to be able to add and subtract these together. I'm passing my first two tests but something is going on with my addition, its giving me a negative number close to the answer but not the right one. Shortened it up a bit.
//For testing
int main()
{
BigInt result;
BigInt num1("999");
BigInt num2("4873");
BigInt num3("-739");
checkTest("Test 1", "999", num1.convertToString());
checkTest("Test 2", "-739", num3.convertToString());
result = num3.add(num4);
checkTest("Test 3", "-10610", result.convertToString());
return 0;
}
Here is where I'm having trouble
#include <iostream>
using namespace std;
class BigInt
{
public:
//An empty constructor, the {} is an empty body
BigInt() {}
BigInt(const char*);
BigInt add(const BigInt&);
BigInt operator+(const BigInt&);
BigInt subtract(const BigInt&);
BigInt operator-(const BigInt&);
string convertToString();
private:
static const int NUM_DIGITS = 100;
int numArr[NUM_DIGITS + 1];
void tensComplement();
};
BigInt::BigInt(const char* str) {
// TODO: CONVERT C-STRING TO BIGINT
int len = strlen(str) - 1;
int zero = NUM_DIGITS - 1;
for (int i = 0; i < NUM_DIGITS; i++){
numArr[i] = 48;
}
for (int i = len; i >= 0; i--){
numArr[zero] = str[i];
zero--;
}
}
BigInt BigInt::add(const BigInt& rightOperand) {
BigInt objToReturn("0");
// TODO: ADD LOGIC HERE
int carry = 0;
for (int i = 100; i > 0; i--){
int left = this->numArr[i] - 48;
int right = rightOperand.numArr[i] - 48;
int total = left + right;
total += carry;
if (total > 9){
carry = 1;
}else{
carry = 0;
}
total = total % 10;
objToReturn.numArr[i] = total + 48;
}
//num1 is the this object
cout << this->numArr[NUM_DIGITS];
//num2 is the rightOperand object
cout << rightOperand.numArr[NUM_DIGITS];
return objToReturn;
}
BigInt BigInt::operator+(const BigInt& rightOperand){
return add(rightOperand);
}
string BigInt::convertToString(){
// TODO: VALUE IN numArr CONVERTED TO STRING
int count = 0;
string str;
if(numArr[0] == 57){
tensComplement();
}
for (int i = 0; i < NUM_DIGITS; i++){
if(numArr[i] == 48 && count == 0){
}else{
str.push_back(numArr[i]);
count++;
}
}
return str;
}
void BigInt::tensComplement(){
// TODO: TENS COMPLEMENT OF THIS NUMBER
for (int i = 0; i <= 100; i++) {
numArr[i] = 9 - numArr[i];
}
numArr[NUM_DIGITS] += 1;
for(int i = NUM_DIGITS; i >= 1; i--){
if(numArr[i] == 10){
numArr[i] = 0;
numArr[i - 1] += 1;
}
}
if(numArr[0] == 1){
numArr[0] = 9;
}
}
//This helps with testing.
bool checkTest(string testName, string whatItShouldBe, string whatItIs) {
if (whatItShouldBe == whatItIs) {
cout << "Passed " << testName << " last digit was: " << whatItIs.at(whatItIs.length()-1) << endl;
return true;
}
else {
if (whatItShouldBe == "") {
cout << "**Failed test " << testName << " ** " << endl << " Output was "<< whatItIs << endl << " Output should have been blank. " << endl;
} else {
cout << "**Failed test " << testName << " ** " << endl << " Output was "<< whatItIs << endl << " Output should have been " << whatItShouldBe << endl;
}
return false;
}
}
This looks like "home-work" but any way.
You would probably benefit from detecting negative values in the constructor and storing that information in a flag. This makes it easier to decide how to use the number in calculations.
As Roddy said you would probably benefit from keeping the digits as numbers instead of characters, reasonably you would be implementing more calculations than displays in BigInt and you will not need to convert things for each calculation, just imagine what it would be like to handle multiplication and division like you do add.
You might benefit from implementing the subtract method before trying to make "add" do subtraction.
I would guess you have two main problems with subtraction,
the four permutations of signs and "borrowing" instead of carry.
Have you planed for any compare method?
main() for testing would give you more value if you kept all your tests in it.
The main in your question have only one assert.
If you keep the asserts for the already implemented functionality you ensure that it keeps working while you add new behavior.
Try to figure out your edge cases and keep a test for each.
Also try to remember that you do not need to implement the whole functionality at once, verifying a small piece that you can see how to do might help you to reason about the rest of the problem.
Your "checkTest" function returns a boolean, use it to count the number of failed tests and return that to give you the ability to fail the build when any test fails.
You need to have a return value telling if any test failed, because in a larger build test-failures will disappear in the noise unless they "scream" at you, e.g. by failing the build.
I hope this helps you find a solution and learn from the problem.

Why does the answer print out twice?

I made a program that returns the product abc where a,b,c are pythagorean triples and add up to 1000. The program does output the correct answer but does it twice. I was curious as to why this is so. After playing around with it a bit I found out that it prints out when a = 200 b = 375 c = 425. And once again when a = 375 b = 200 c = 425.
bool isPythagTriple(int a, int b, int c);
int main()
{
for(int a = 1; a < 1000; a++)
{
for(int b = 1; b < 1000; b++)
{
for(int c = 1; c < 1000; c++)
{
if( ((a+b+c)==1000) && isPythagTriple(a,b,c) )
{
cout << a*b*c << " ";
break;
}
}
}
}
return 0;
}
bool isPythagTriple(int a, int b, int c)
{
if( (a*a)+(b*b)-(c*c) == 0 )
return true;
else
return false;
}
Just for what it's worth, I'd write this function:
bool isPythagTriple(int a, int b, int c)
{
if( (a*a)+(b*b)-(c*c) == 0 )
return true;
else
return false;
}
More like this:
bool isPythagTriple(int a, int b, int c) {
return a*a+b*b==c*c;
}
Break, in this case, will only break out of the c loop, not the b and a ones.
A quick fix is to ensure you don't get repeats by starting each variable greater than or equal to the previous (so b is never less than a and c is never less than b).
In addition, you can actually get rid of the c loop altogether since there's only one value of c that is valid for a given a,b pair (unless a + b + c > 1000 in which case there are none). I would try something like:
for (int a = 1; a < 1000; a++) {
for (int b = a; b < 1000; b++) {
int c = 1000 - a - b;
if (c >= b) {
if (isPythagTriple (a,b,c)) {
cout << a << " " << b << " " << c << " " << a*b*c << std::endl;
}
}
}
}
The overall effect of that is to reduce the total loop count from a billion (short scale) to about half a million hence reducing it by about 99.95% - that should be a tiny bit faster :-)
And potentially making it faster with Jerry Coffin's suggestion as well (and an inline suggestion to the compiler), a full program:
#include <iostream>
inline bool isPythagTriple(int a, int b, int c) {
return a * a + b * b == c * c;
}
int main() {
for(int a = 1; a < 1000; a++) {
for(int b = a; b < 1000; b++) {
int c = 1000 - a - b;
if (c >= b) {
if (isPythagTriple(a,b,c)) {
std::cout << a << " " << b << " " << c << " "
<< a*b*c << std::endl;
}
}
}
}
return 0;
}
which takes 0.004 seconds on average (system + user) on my box, with the original taking about 2.772 seconds on average (ten samples each). Not that it really matters unless you're running it many, many times, of course.
The output of that code is, as expected:
200 375 425 31875000
This is how break and continue work - break only exits the inner-most loop. Read the discussion on this question for some alternatives to this.
The reason this happens is because you only break out of the inner loop (for c). The outer loops carry on running and re-enter the inner loop, meeting the conditions again. There are numerous values that add to 1000 and you are catching some of them - you have caught 2, as your print indicates. You could use "return" instead of break if you want only the first combination of values output.
As for the "code block" I am not sure what you mean.. You already seem to know to write functions. If what you mean is a scope block, then you simply enclose the code of concern in curly braces -> { }
E.g.
{
int i = 0;
i++;
}
To prevent multiple orderings of the solutions, make sure that c >= b >= a. You can do this by changing the lower bounds:
for(int a = 1; a < 1000; a++) {
for(int b = a; b < 1000; b++) {
for(int c = b; c < 1000; c++) {