ChatGPTにヒントを貰いながらソースコードの修正を試みた

# はじめに
　ChatGPTはソースコードを学習しているようなので、プログラミングの助っ人として期待が持てますが、実際にどれくらい役に立つのか、最短経路を求めるプログラムを例に実験してみました。
　結論としては、日本語でのプログラミングの支援にそこそこ使えることは分かりました。下記の記事にも日本語プログラミングの内容を書いたので、良かったら見てやってください。
  [ChatGPTを使って日本語でプログラミングしてみる](https://note.com/oki_mebarun/n/n412df53af5fc)

# 日本語で修正依頼してみる
　はじめに、経路のループを検知出来てない最短経路を求める関数を使って、日本語で修正を依頼してみます。
```python:[Query]
駅名ｘが与えられたら、ｘと接続している駅名と所要時間の辞書を返す関数station_xがある。
次のコードはstation_xを使って、駅ｘと駅ｙの最短経路を求めるコードだが、
ルートを巡回する場合に無限ループに陥る恐れがある。
そこで、以下の方針で関数find_routeを修正しなさい。
１．訪問済みの駅名のリストを関数find_routeの引数に追加して、
１つの駅を２回通らない最短経路を求めるようにする。
２．関数find_routeの戻り値を最短所要時間と見つかった最短ルートの文字列の２つにする。
def find_route(x, y):
    cand_x = station_x(x)
    if y in cand_x:
        min_time = cand_x[y]
    else:
        min_time = float("inf")

    for z in cand_x:
        xtoz = cand_x[z] + find_route(z, y)
        if xtoz < min_time:
            min_time = xtoz
            min_z = z
    return min_time
```

　それでは、ChatGPT先生の回答を見てみましょう。

```python:[Answer by ChatGPT]
def find_route(x, y, visited=[]):
    cand_x = station_x(x)
    if y in cand_x:
        min_time = cand_x[y]
        route = x + "→" + y
    else:
        min_time = float("inf")
        route = ""

    for z in cand_x:
        if z not in visited:
            visited.append(z)
            xtoz = cand_x[z] + find_route(z, y, visited)
            if xtoz < min_time:
                min_time = xtoz
                min_z = z
                route = x + "→" + z + "→" + route
    return min_time, route
```

どうやら、意図を酌んで貰った部分とそうでない部分があるようですね。

+ 引数`visited`を追加したのは良いものの、`visited.append(z)`をループ内でしているので、余計な駅まで追加されてしまっている。
+ 最短ルートの文字列は`x→y`の部分は良いものの、ループ中でくっ付ける部分がバグっている。
+ `find_route`の戻り値を２つにしているものの、途中でそれを忘れている。

# 英語で修正依頼してみる
　一説によると、ChatGPTの学習データは英語の方が圧倒的にボリュームが多いので、英語で指示した方がより高度な回答が返ってくるらしいとの噂があります。そこで、同じことを英語で質問してみました。

```python:[Query]
Output a Python code by following the instructions below:
1. The function station_x returns a dictionary,
 when it is called with an argument x,
 where stations which connect to x are the keys and 
 the ride time between each stations and x are the values.
2. The function find_route returns the minimum ride time that
 is a sum of ride times between stations in the route that start from x and end to y.
3. Add an argument that represents visited stations to find_route
 in order to avoid to visit a same station twice.
4. The function find_route returns the minimum ride time and
 a string that represents the minimum route from x to y.

def find_route(x, y):
    cand_x = station_x(x)
    if y in cand_x:
        min_time = cand_x[y]
    else:
        min_time = float("inf")

    for z in cand_x:
        xtoz = cand_x[z] + find_route(z, y)
        if xtoz < min_time:
            min_time = xtoz
            min_z = z
    return min_time
```

　それでは、ChatGPT先生の回答を見てみましょう。

```python:[Answer by ChatGPT]
def find_route(x, y, visited=[]):
    cand_x = station_x(x)
    if y in cand_x:
        min_time = cand_x[y]
    else:
        min_time = float("inf")

    for z in cand_x:
        if z not in visited:
            visited.append(z)
            xtoz = cand_x[z] + find_route(z, y, visited)
            if xtoz < min_time:
                min_time = xtoz
                min_z = z
    return min_time, min_z
```

日本語で質問した時とほとんど同じコードですが、最短ルート文字列が抜けている分劣化しています。。。

# ChatGPTの回答のバグをヒトが修正してみる

　日本語で質問したときの回答ソースコードのバグを直しました。station_xのコードと合わせて記載します。

```python:[完成版]
# 1. 次のペアの駅名と列車の所要時間を辞書で定義する
station_time = {('大宮','新宿'):32, ('新宿','武蔵小杉'):21, ('新宿','品川'):19, ('大宮','西国分寺'):45, ('西国分寺','武蔵小杉'):41, ('西国分寺','新宿'):28, ('武蔵小杉','川崎'):12, ('品川','川崎'):9}

# 2. 駅名xが与えられたら、1の辞書に含まれるxでない方の駅名と所要時間の辞書を作成し返す
def get_other_station(x):
    other_station_time = {}
    for key, value in station_time.items():
        if x in key:
            other_station = list(key)
            other_station.remove(x)
            other_station_time[other_station[0]] = value
    return other_station_time

# 3. 上記1と2を実行する関数をstation_x(x)と定義する
def station_x(x):
    return get_other_station(x)

# ヒトによるデバッグ版
def find_route(x, y, visited=[]):
    cand_x = station_x(x)
    if y in cand_x:
        min_time = cand_x[y]
        min_route = f"{x} to {y} by {min_time}."
    else:
        min_time = float("inf")
        min_route = ""

    min_z = None
    for z in cand_x:
        if z not in visited:
            tmp_time, tmp_route = find_route(z, y, visited + [z]) 
            xtoz = cand_x[z] + tmp_time
            if xtoz < min_time:
                min_time = xtoz
                min_z = z
                min_route = tmp_route

    if min_z is not None:
        best_route = f"{x} to {min_z} by {cand_x[min_z]}, " + min_route
    else:
        best_route = min_route
    return min_time, best_route

# 表示用の関数
def do_find_route(x, y):
    visited = [x]
    min_time, best_route = find_route(x,y, visited)
    print(f"min time from {x} to {y} is {min_time} by the route: {best_route}")
```

### 実行結果

それでは、実行結果を確認しましょう。
まずは、通常の時間の場合です。
```python
"""
通常
"""
station_time = {('大宮','新宿'):32, ('新宿','武蔵小杉'):21, ('新宿','品川'):19, ('大宮','西国分寺'):45, ('西国分寺','武蔵小杉'):41, ('西国分寺','新宿'):28, ('武蔵小杉','川崎'):12, ('品川','川崎'):9}
do_find_route('川崎','大宮')
do_find_route('品川','大宮')

"""output
min time from 川崎 to 大宮 is 60 by the route: 川崎 to 品川 by 9, 品川 to 新宿 by 19, 新宿 to 大宮 by 32.
min time from 品川 to 大宮 is 51 by the route: 品川 to 新宿 by 19, 新宿 to 大宮 by 32.
"""
```

正しく経路が求められているようです。
次に、埼京線が遅延した場合を計算してみましょう。

```python
"""
遅延
"""
station_time = {('大宮','新宿'):32+60, ('新宿','武蔵小杉'):21, ('新宿','品川'):19, ('大宮','西国分寺'):45, ('西国分寺','武蔵小杉'):41, ('西国分寺','新宿'):28, ('武蔵小杉','川崎'):12, ('品川','川崎'):9}
do_find_route('川崎','大宮')
do_find_route('品川','大宮')

"""output
min time from 川崎 to 大宮 is 98 by the route: 川崎 to 武蔵小杉 by 12, 武蔵小杉 to 西国分寺 by 41, 西国分寺 to 大宮 by 45.
min time from 品川 to 大宮 is 92 by the route: 品川 to 新宿 by 19, 新宿 to 西国分寺 by 28, 西国分寺 to 大宮 by 45.
"""
```

ちゃんと埼京線を回避したルートを計算出来ているようです。

# おわりに
　ChatGPTにソースコードの修正を依頼してみましたが、惜しい部分があるものの、バグが残る結果となりました。また、英語で指示を出しても特に改善する訳ではなさそうです。指示文の英語が不味いせいかもしれませんが（>_<）。
　ともあれ、ソースコードを渡して部分的に直すことにヒント的に使えるレベルにはあるようなので、ヒトのデバッグと組み合わせて使えば生産性の向上に繋がるかもしれませんね。