20

Project Eulerの問題 9 を解決しています。私のソリューションでは、「goto」ステートメントを使用して 2 つの for ループから抜け出します。問題は次のとおりです。

ピタゴラスのトリプレットは、3 つの自然数 abc のセットです。

a^2 + b^2 = c^2

たとえば、3^2 + 4^2 = 9 + 16 = 25 = 52 です。

a + b + c = 1000 であるピタゴラスの 3 連符が 1 つだけ存在します。積 abc を見つけます。

私の解決策は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;

「goto」ステートメントは C++ プログラマーの間ではあまり一般的ではないため、これが「goto」の合理的な使用法と見なされるかどうかを知りたいです。または、「goto」を必要としない問題のより良い解決策がある場合。これは、単に「goto」を回避するソリューションではなく、アルゴリズムを改善する方法で「goto」を回避するソリューションを意味します。

4

6 に答える 6

46

returnは「構造化された」gotoものであり、多くのプログラマーがより受け入れやすいと感じています。それで:

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;
}
于 2009-06-21T17:45:37.290 に答える
18

gotoこのような状況で使用するのは問題ないと思います。

ところで、goto に対する見下すような説教は、通常、他の人が言っているのを聞いたり、どこかで読んだりしたことをただオウム返しする人々から来ています..

于 2009-06-21T20:05:19.257 に答える
6

2つのループから抜け出すことについてのこの質問を参照してください。gotoを使用するよりもはるかに優れた回答が提供されます。

提供される最善の答えは、2番目のループを関数に配置し、最初のループ内からその関数を呼び出すことです。

mquanderの応答からコピーされたコード

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;
    }
}

この場合、gotoを使用することは、子猫を殺すほど悪くはないと思いますが。しかし、それは近いです。

于 2009-06-21T17:45:36.057 に答える
4

より良い代替案が思い浮かびません。しかし、使用しない別の方法の 1 つgotoは、最初のfor-loop を変更することです。

for (a = 1; a<sum && result == -1; a++){

次にbreak、2 番目のループから抜けforます。2 番目の-loop が によって破られた-1後に結果が決してないと仮定すると、それは機能します。forbreak

于 2009-06-21T17:30:09.510 に答える
4

先頭でa を宣言し、 for ループ条件 (およびの後)bool found = falseに追加し、現在の goto がある場所で found を true に設定できます。次に、見つかったことが真であることを条件として出力を作成します。&& !founda < sumb < sum

于 2009-06-21T17:32:40.207 に答える
1
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);

最適化された結果も.. :P

とにかくゴトスが大好き!

于 2011-12-24T13:41:06.600 に答える