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.
I just found this on the "Related" sidebar. An interesting thread overall, but in particular, this is an answer to my question.
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!