配列を使っても自動的に組み合わせが解決されるわけではないから、何か組み合わせを見つける方法は作らなくてはいけないよ。
配列を使って先に計算結果を入れておけばそれがキャッシュになる。
でもそれは、多少速度が速くなるかもね、程度のもの。
解き方は色々ある。
一番シンプルなのは以下のような方法。
for 文と if 文で解いたってSubasicさんの回答もこういうのだと思う。
C#
1for (int a = 1; a <= 100; ++a)
2{
3 for (int b = 1; b <= 100; ++b)
4 {
5 for (int c = a > b ? a : b; c <= 100; ++c)
6 {
7 if (a * a + b * b == c * c)
8 {
9 Result(a, b, c);
10 }
11 if (a * a + b * b <= c * c)
12 {
13 break;
14 }
15 }
16 }
17}
配列2つを組み合わせることはできる…のだが、何番目同士の要素を組み合わせているかわかる方法が添え字をつけない限りないため、for 文を3つ回す以外で「a, b, c」を得る方法がない。
このため、配列を使っても上記とあまり大差ないコードになりがち。
より複雑にして、要素自体を参照した際に a, b, c が取れるようにすることはできる。
でも随分複雑だし、いい方法とは言えない。
情報を持てる構造体を作り
C#
1public struct LeftHandSide
2{
3 public LeftHandSide(int a, int b)
4 {
5 this.a = a;
6 this.b = b;
7 }
8
9 public int a { get; }
10 public int b { get; }
11 public int Value { get { return a * a + b * b; } }
12}
13
14public struct RightHandSide
15{
16 public RightHandSide(int c)
17 {
18 this.c = c;
19 }
20
21 public int c { get; }
22 public int Value { get { return c * c; } }
23}
2つの配列の一致したものを取り出す。
C#
1// 配列に直接いれるよりそのコンテナを使う
2// 予めサイズは必要数分確保しておく
3var lefts = new List<LeftHandSide>(100 * 100);
4for (int a = 1; a <= 100; ++a)
5{
6 for (int b = 1; b <= 100; ++b)
7 {
8 lefts.Add(new LeftHandSide(a, b));
9 }
10}
11
12var rights = new RightHandSide[100];
13for (int c = 1; c <= 100; ++c)
14{
15 rights[c - 1] = new RightHandSide(c);
16}
17
18// Linqを使って、2つの配列の交差した結果を取り出す
19var results = lefts.Join(
20 rights,
21 left => left.Value,
22 right => right.Value,
23 (left, right) => new { left.a, left.b, right.c });
24
25foreach (var result in results)
26{
27 Result(result.a, result.b, result.c);
28}
早い方法とは言い難い。
メモリも沢山いるしね。
cだけを予め計算しておき、その組み合わせを探す場合はもっと簡単な方法がある。
Dictionaryを使う方法だ。
Dictionaryを使って、二乗したcの結果と、cの組み合わせを得られるようにする。
そうすれば、高速に一致するcがあるのかが分かる。
この場合、コンテナもcの結果だけで済む。
C#
1// 予め c の二乗と c の組み合わせを計算しておく。
2var candidates = new Dictionary<int, int>();
3for (int c = 1; c <= 100; ++c)
4{
5 candidates[c * c] = c;
6}
7
8for (int a = 1; a <= 100; ++a)
9{
10 for (int b = a; b <= 100; ++b)
11 {
12 // cが見つかれば一致する整数があったということ
13 int c;
14 if (candidates.TryGetValue(a * a + b * b, out c))
15 {
16 Result(a, b, c);
17 }
18 }
19}
1から100までの数値ならa*a + b*b
の平方根を求める方法もある。
その結果が整数であるかどうかでピタゴラスの定理を満たす整数を知る。
あまりに大きい数値だと平方根の計算速度が不安だが、この数なら関係はない。
C#
1for (int a = 1; a <= 100; ++a)
2{
3 for (int b = 1; b <= 100; ++b)
4 {
5 double sqrt = Math.Sqrt(a * a + b * b);
6
7 // 端数を切り落とし一致するかを調べることで、整数であることを知る
8 if (sqrt == Math.Floor(sqrt))
9 {
10 int c = (int)sqrt;
11 if (c <= 100)
12 {
13 Result(a, b, c);
14 }
15 }
16 }
17}
なお、プログラム的な書き方で以下のように書くこともできる。
C#
1for (int a = 1; a <= 100; ++a)
2{
3 for (int b = a; b <= 100; ++b)
4 {
5 // とりあえずcを整数値に変換する
6 int c = (int)Math.Sqrt(a * a + b * b);
7
8 // 結果が一致しなければ整数の平方根ではなかったということ
9 if (c <= 100 && a * a + b * b == c * c)
10 {
11 Result(a, b, c);
12 }
13 }
14}
結果を出力するResult関数は以下。
public static void Result(int a, int b, int c)
{
Console.WriteLine($"{a} * {a} + {b} * {b} = {c} * {c}");
Console.WriteLine($"{a * a} + {b * b} = {c * c}");
Console.WriteLine();
}