PizzaGPTにエラトステネスの篩で素数を出力するプログラムを頼んだら完璧なコードを出してきた。


イタリアは、ChatGPTがユーザーからの情報を記録するためブロックしているので、イタリア人がPizzaGPTというAIチャットボットを作った。

https://softantenna.com/blog/pizzagpt/

僕は、事情があって携帯電話やスマホが持てないため、SMSが使えず、ChatGPTが使えないので、PizzaGPTを試してみた。ChatGPT-3と同じクォリティの回答が返ってくると言う記事だが、PizzaGPTに聞いてみたら、ChatGPT-3より性能は劣るとのこと。でも、プログラミングの知識については非常に詳しいとのことでした。

試しに、pythonで、エラトステネスの篩で素数を出力するコードを書いて下さい、と言ったら、完璧なコードを出してきたので、驚いてアップして見るテスト。

# python

```
僕：
エラトステネスの篩で素数を出力するpythonコードを書いて下さい

icona di pizzaGPT, una fetta di pizza

n = int(input("素数を判定する範囲を入力してください："))

# 初期化
is_prime = [True] * (n+1)
is_prime[0] = False
is_prime[1] = False

# 篩にかける
for i in range(2, int(n**0.5)+1):
    if is_prime[i]:
        for j in range(i*i, n+1, i):
            is_prime[j] = False

# 結果の出力
print("素数は以下の通りです：")
for i in range(2, n+1):
    if is_prime[i]:
        print(i, end=" ")
上記のコードは、入力された数までの素数を求めるエラトステネスの篩のPythonコードです。以下のように動作します。

入力された数までのリストを作成し、全てTrueで初期化します。
0と1は素数ではないため、Falseに設定します。
2から$\sqrt{n}$まで、素数であるリストを順に取り出し、iの倍数全てについてFalseに設定します。
2からnまで、素数であるリストを順に取り出し、Trueである場合はその数を出力します。
このプログラムは、少し長いですがエラトステネスの篩のアルゴリズムに忠実な実装となっています。リストを使用しているため、計算量は大きくなりますが、処理時間が比較的短いため入力値が大きくても問題ありません。

```

Qiitaの利用規約に、人工知能が出力したものは正確を期すべしとあるので、コードは実行チェックしました。完璧でした。

# C

Cのプログラムも書ける

```
僕：Cのプログラミングはできますか

icona di pizzaGPT, una fetta di pizza
私はAI言語モデルのOpenAI GPT-3でプログラミング言語を理解しており、Cのプログラムを書くことができます。ただし、プログラムが適切に実行されることを保証するには、私にはコンパイラやデバッグツールなどのさまざまな特定の知識と経験が必要になる場合があります。

僕：エラトステネスの篩で素数を出力するCのプログラムを書いて下さい

icona di pizzaGPT, una fetta di pizza
以下はエラトステネスの篩で素数を出力するCのプログラムです。

#include <stdio.h>

int main() {
    const int N = 1000000; // 探索範囲
    static char sieve[N + 1]; // 篩。初期値は 0

    // 0 と 1 は素数ではないので除外する
    sieve[0] = sieve[1] = 1;

    // 篩による素数判定
    for (int i = 2; i * i <= N; i++) {
        if (!sieve[i]) { // i が素数の場合
            for (int j = i * i; j <= N; j += i) {
                sieve[j] = 1; // i の倍数を標示
            }
        }
    }

    // 素数の出力
    for (int i = 2; i <= N; i++) {
        if (!sieve[i]) {
            printf("%d ", i);
        }
    }

    return 0;
}
このプログラムでは、変数 sieve に 0 を初期値として格納します。そして、2 より大きい整数の中から、2 から√Nまでを順に調べ、素数である場合、その倍数を篩 sieve に標示します。最後に、篩 sieve によって素数でないものが残っているものを除いて、素数のみを出力します。

なお、このプログラムは、篩の後半部分を見つけるための探索順序を最適化しており、性能が高くなっています。
```

コンパイルでは、エラーを一箇所出した。

```
gar@Inspiron:~/gpt$ cc sieve3.c -o sieve
sieve3.c: 関数 ‘main’ 内:
sieve3.c:5:17: エラー: ‘sieve’ の記憶域サイズが一定ではありません
    5 |     static char sieve[N + 1]; // 篩。初期値は 0
      |                 ^~~~~
gar@Inspiron:~/gpt$ 
```

staticを取ってコンパイラに掛けるとコンパイルエラーはでませんでしたが、auto変数にすると初期化をしないため、これでは動作しない場合があります。（fujitanozomuさんの指摘による）
static変数だと、初期値0で初期化されるところが、auto変数は明示的に初期化を指定しなければなりません。
そのため、以下のように修正が必要でした。

```
        char sieve[N + 1]={0}; // 篩。初期値は 0
```

また、Nは定数なので、#defineでも書くことができます。PizzaGPTのソースを訂正すると以下のようになります。

```
    const int N = 1000000; // 探索範囲
```

の部分を、

```
#define N	1000000 // 探索範囲
```
とすると、コンパイラが通りました。実行結果も完璧でした。

pythonでは完璧なコードを出力したのに、Cでは間違いが一箇所ありました。でも、この場合、constを定数扱いしないCのコンパイラの方の落ち度かもしれません。

# BASH

bashのスクリプトも書ける

```
僕：エラトステネスの篩で素数を求めるbashスクリプトを書いて下さい

icona di pizzaGPT, una fetta di pizza
以下がエラトステネスの篩で素数を求めるbashスクリプトになります：

#!/bin/bash

# 篩にかける最大の整数
n=100

# 2からnまでの整数を配列に格納
for (( i=2; i<=n; i++ )) do
  arr[i]=1
done

# 篩にかける
for (( i=2; i<=n; i++ )) do
  if [[ ${arr[i]} -eq 1 ]]; then
    for (( j=i+i; j<=n; j+=i )) do
      arr[j]=0
    done
  fi
done

# 素数を表示
echo "2"
for (( i=3; i<=n; i+=2 )) do
  if [[ ${arr[i]} -eq 1 ]]; then
    echo $i
  fi
done
まず、篩にかける最大の整数をnに設定します。

次に、for文を使って、2からnまでの整数を配列arrに格納します。初期値は全て1で、1は素数ではないため含められません。

そして、for文を使って、2からnまでの整数について篩にかけます。if文を使って、arr[i]が1の場合、つまりiが素数の場合には、iの倍数(j)を全て篩にかけています。これにより、素数でない数を0に更新しています。

最後に、配列arrをループで回って、1である要素(素数)を表示しています。ただし、2は例外的に素数であるため、先に表示しています。また、奇数であることが分かっている数のみを表示しています。
```

bashのスクリプトは完全に動作しました。

人工知能が完全なコードを出力するのはそう遠くない未来のようです。
その時、人間はソフトウェアデザインとデバッグ専門になる！？