ChatGPTにプログラム作成を間違って依頼した結果

# 経緯
Java初心者向けの課題で、「魔方陣の組み合わせを検出するプログラムを作りましょう」というのをだいぶ前にやったことがあるのですが、これをChatGPTに作ってもらいました。
ところが、頼み方を間違った結果、意外な結果になってしまったので記録しておきます。

:::note warn
この記事で利用している生成AIはOpenAI ChatGPTの**Free Trial**です。有償のサブスクリプションでは結果が違うと思います。
:::

# プログラムを作ってと言ったら

早速、以下の注文をしてみました。
> 以下のプログラムを作成してください。
> * ３×３の２次元配列を作成する。
> * 各マスに１～９の数字を入れる。
> * 縦、横、斜めのマスをそれぞれ合計した数値が同じになる組み合わせをすべて求める。

ということで、作成してくれたプログラムが以下の通りです。

```python
import itertools

# 3x3の2次元配列を作成
grid = [[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]]

# 合計値が同じになる組み合わせを保存するリスト
result = []

# 1〜9の数字の組み合わせを生成
numbers = list(range(1, 10))
combinations = itertools.permutations(numbers)

# 合計値が同じになる組み合わせを探索
for combination in combinations:
    a, b, c, d, e, f, g, h, i = combination
    if (a + b + c == d + e + f == g + h + i ==  # 横方向
        a + d + g == b + e + h == c + f + i ==  # 縦方向
        a + e + i == c + e + g):  # 斜め方向
        result.append(combination)

# 結果を出力
for combination in result:
    a, b, c, d, e, f, g, h, i = combination
    grid[0][0], grid[0][1], grid[0][2] = a, b, c
    grid[1][0], grid[1][1], grid[1][2] = d, e, f
    grid[2][0], grid[2][1], grid[2][2] = g, h, i

    # 合計値が同じになる組み合わせを表示
    print(grid)
    print('---')
```

あ、そうか。プログラミング言語を指定するのを忘れてました。
Pythonではちゃんと作れてますが、課題はJavaなのでJavaで作り直してもらいます。

# Javaで作り直して
そこで、以下のようにお願いしました。

> Javaで作成してください。

すると、前のプログラムをJavaで作り直してくれました。もう一度プログラムの仕様を書く必要はないんだなとぁ。さすがチャット型インタフェース!

作成してくれたプログラムが以下の通りです。

```Java
import java.util.ArrayList;
import java.util.List;

public class MagicSquare {

    public static void main(String[] args) {
        int[][] grid = new int[3][3];
        List<int[]> result = new ArrayList<>();

        // 1〜9の数字の組み合わせを生成
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        permute(numbers, 0, result);

        // 合計値が同じになる組み合わせを探索
        for (int[] combination : result) {
            int a = combination[0];
            int b = combination[1];
            int c = combination[2];
            int d = combination[3];
            int e = combination[4];
            int f = combination[5];
            int g = combination[6];
            int h = combination[7];
            int i = combination[8];

            if (a + b + c == d + e + f &&  // 横方向
                a + d + g == b + e + h &&  // 縦方向
                a + e + i == c + e + g) {  // 斜め方向

                result.add(combination);
            }
        }

        // 結果を出力
        for (int[] combination : result) {
            int a = combination[0];
            int b = combination[1];
            int c = combination[2];
            int d = combination[3];
            int e = combination[4];
            int f = combination[5];
            int g = combination[6];
            int h = combination[7];
            int i = combination[8];

            grid[0][0] = a;
            grid[0][1] = b;
            grid[0][2] = c;
            grid[1][0] = d;
            grid[1][1] = e;
            grid[1][2] = f;
            grid[2][0] = g;
            grid[2][1] = h;
            grid[2][2] = i;

            // 合計値が同じになる組み合わせを表示
            printGrid(grid);
            System.out.println("---");
        }
    }

    // 数字の組み合わせを生成するメソッド
    private static void permute(int[] numbers, int start, List<int[]> result) {
        if (start == numbers.length - 1) {
            int[] combination = numbers.clone();
            result.add(combination);
        } else {
            for (int i = start; i < numbers.length; i++) {
                swap(numbers, start, i);
                permute(numbers, start + 1, result);
                swap(numbers, start, i);
            }
        }
    }

    // 配列の要素を交換するメソッド
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // 2次元配列を表示するメソッド
    private static void printGrid(int[][] grid) {
        for (int[] row : grid) {
            for (int num : row) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }
}
```

ふんふん、、**ん?**
**縦横判定のところ、なんか足りなくない?**
これで、ちゃんと判定できるのかなと実行してみたところ、**不完全な魔方陣が大量にできてしまいました。**
やっぱりそうだよなぁ。

# 最初からJavaで

ひょっとしてChatGPTはJavaが苦手?　
さすがにそんなことはないでしょう。最初から、Javaで作ってもらいました。

> 以下のプログラムをJavaで作成してください。
> * ３×３の２次元配列を作成する。
> * 各マスに１～９の数字を入れる。
> * 縦、横、斜めのマスをそれぞれ合計した数値が同じになる組み合わせをすべて求める。

結果は以下の通りです。

```Java
import java.util.ArrayList;
import java.util.List;

public class MagicSquare {
    public static void main(String[] args) {
        int[][] grid = new int[3][3];
        List<int[]> combinations = new ArrayList<>();

        // 1〜9の数字の組み合わせを生成
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        permute(numbers, 0, combinations);

        // 合計値が同じになる組み合わせを求める
        List<int[][]> magicSquares = findMagicSquares(combinations);

        // 結果を出力
        for (int[][] square : magicSquares) {
            printGrid(square);
            System.out.println("---");
        }
    }

    // 数字の組み合わせを生成するメソッド
    private static void permute(int[] numbers, int start, List<int[]> combinations) {
        if (start == numbers.length - 1) {
            int[] combination = numbers.clone();
            combinations.add(combination);
        } else {
            for (int i = start; i < numbers.length; i++) {
                swap(numbers, start, i);
                permute(numbers, start + 1, combinations);
                swap(numbers, start, i);
            }
        }
    }

    // 配列の要素を交換するメソッド
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // 合計値が同じになる組み合わせを求めるメソッド
    private static List<int[][]> findMagicSquares(List<int[]> combinations) {
        List<int[][]> magicSquares = new ArrayList<>();

        for (int[] combination : combinations) {
            int[][] square = {
                    {combination[0], combination[1], combination[2]},
                    {combination[3], combination[4], combination[5]},
                    {combination[6], combination[7], combination[8]}
            };

            if (isMagicSquare(square)) {
                magicSquares.add(square);
            }
        }

        return magicSquares;
    }

    // 合計値が同じになるかを判定するメソッド
    private static boolean isMagicSquare(int[][] square) {
        int sum = square[0][0] + square[0][1] + square[0][2]; // 上段の合計値

        // 横方向の合計値をチェック
        for (int i = 1; i < 3; i++) {
            int rowSum = square[i][0] + square[i][1] + square[i][2];
            if (rowSum != sum) {
                return false;
            }
        }

        // 縦方向の合計値をチェック
        for (int i = 0; i < 3; i++) {
            int colSum = square[0][i] + square[1][i] + square[2][i];
            if (colSum != sum) {
                return false;
            }
        }

        // 斜め方向の合計値をチェック
        int diag1Sum = square[0][0] + square[1][1] + square[2][2];
        int diag2Sum = square[0][2] + square[1][1] + square[2][0];
        if (diag1Sum != sum || diag2Sum != sum) {
            return false;
        }

        return true;
    }

    // 2次元配列を表示するメソッド
    private static void printGrid(int[][] grid) {
        for (int[] row : grid) {
            for (int num : row) {
                System.out.print(num + " ");
            }
            System.out.println();
        }
    }
}
```

今度はちゃんとできました!

# まとめ
今回のケースでは、Pythonで作成したプログラムをJavaに変換するのがうまくいかなかったのか、それとも「さっきのをJavaでもう一度」という依頼に対する手順が良くなかったのか、いずれにしても最初からJavaで依頼しないと間違った回答になるという結果でした。

生成AIは、プログラミングが得意だという話を聞いたことがあります。
でも、頼み方を間違えると間違った回答が返るかもしれないという経験ができました。

そもそも、どういうプログラムを作ってもらうにしても、結果を検証することができなければ利用できないというところでしょうか。

ただ、これほど単純なプログラムであればすぐに検証できますが、それこそAIのロジックのような複雑なプログラムをAIに作成させて、それを人間が検証するって大変ですよね。では複雑な検証はAIに任せましょうというようなことになるんだろうか。。。

個人的には、Pythonのソースは変数の使い方とかいかにもAIっぽいソースだなぁと思ったのですが、最後のJavaのソースはなんだか人間臭いのが気になりました。これは気のせいかな?