memorandums

日々の生活で問題解決したこと、知ってよかったことなどを自分が思い出すために記録しています。

コード生成できちゃうのか。。。

あまり関係ないけど絵の練習。。。指が。。。変なオブジェクトがキーボードから生えている。。。もう眠たいので諦めた。

さて、本題。

担当科目の1つ、ソフトウェア工学の1コマでMSR (Mining Software Repository)っぽいのを演習でやってもらっています。学部3年生対象です。

複雑なコードほど欠陥が多くなる?という仮説をGitリポジトリのデータを使って検証しようという流れです。

複雑度はおなじみサイクロマチック複雑度(今はなきSourceMonitorで取得)を使用し、欠陥数はコミットログにfixが含まれる個数とします。それらをLinuxコマンドを組み合わせてデータ抽出して(←Pythonで完結しそうですがLinuxコマンドの練習も兼ねています)相関係数を求めようという流れになります。

で、途中で2つPythonコードを書いてもらう(以前はRuby)ことにしています。面倒な人は手で編集しなさいという崖から突き落とすパターンです。実際に楽したければコード書けばいいし、面倒なら手でやるのが普通だと思いますので。どちらを選択するかは人によるでしょう。

これちょっとしたプログラミング練習にもなるのでいいなと思ってきたんです。試しにChatGPTにお願いしてみたんですね。。。したらすぐにできました。いやはや。。。💦 プロンプトがかけるかどうかによりますが。

プログラム1

以下の入力を与えたら出力を表示するプログラムになります。要は連続した行数をカウントしてカンマ区切りで個数を追加する感じの使用になります。

入力

AboutDialog.java
AllDefaultPossibilitiesBuilder.java
AllDefaultPossibilitiesBuilder.java
AllInternalTests.java
AllInternalTests.java
以下略

出力

AboutDialog.java, 1
AllDefaultPossibilitiesBuilder.java, 2
AllInternalTests.java, 2
以下略

プログラム2

仕様は講義資料では以下の絵で説明しています。

まぁ、どちらもツールとしてはよくあるタイプのプログラムじゃないかと思います。Pythonの便利ライブラリを使いこなせば瞬殺できるかもですが学生さんにはちょうどいい練習になるかなと思ったんです。3年生ですからこれくらいはできて欲しいわけです。

では、ChatGPTに上記のコードを生成するプロンプトを書いてみいます。仕様を書くというよりは例示すれば類推してくれそうだと思いました。

プログラム1

プロンプト:

以下の入力に対して出力を表示するpythonのコードを教えて下さい。以下はあくまで例です。データはキーボードから与えます。

# 入力
AboutDialog.java
AllDefaultPossibilitiesBuilder.java
AllDefaultPossibilitiesBuilder.java
AllInternalTests.java
AllInternalTests.java

# 出力
AboutDialog.java, 1
AllDefaultPossibilitiesBuilder.java, 2
AllInternalTests.java, 2

以下、生成されたコードです。ご丁寧に入力方法(終了方法)まで書いてくれています。頭が下がります。

from collections import Counter
import sys

print("ファイル名を1行ずつ入力してください。終了するには Ctrl+D (Mac/Linux) または Ctrl+Z + Enter (Windows) を押してください。")

# キーボードから複数行の入力を受け取る
lines = [line.strip() for line in sys.stdin if line.strip()]

# 出現回数をカウント
counts = Counter(lines)

# 結果を出力(入力順を保つ)
for filename in dict.fromkeys(lines):
    print(f"{filename}, {counts[filename]}")

プログラム2

プロンプト:

以下の仕様のc2.csvとf3.csvとans.csvがあるとします。c2.csvとf2.csvからans.csvを出力するpythonコードを教えて下さい。以下はあくまで例です。

# c2.csv
AboutDialog.java, 0.1
AllDefaultPossibilitiesBuilder.java, 0.2

# f3.csv
AllDefaultPossibilitiesBuilder.java, 2
AllInternalTests.java, 2

# ans.csv
AboutDialog.java, 0.1, 0
AllDefaultPossibilitiesBuilder.java, 0.2, 2

以下が生成されたコードです。恐ろしいですね。。。上記の図はプロンプトには与えていませんが、例となるデータからc2.csvが基準であること、f3.csvにデータがなければ0を補うことを類推してくれました。凄い。。。pandasを使えばいいんですね。。。こういうの。楽ちんです。

import pandas as pd

# CSVファイルの読み込み(ヘッダーがないことを前提)
df_c2 = pd.read_csv("c2.csv", header=None, names=["filename", "val1"])
df_f3 = pd.read_csv("f3.csv", header=None, names=["filename", "val2"])

# 左結合(c2を基準)
merged = pd.merge(df_c2, df_f3, on="filename", how="left")

# val2 が欠損(NaN)の場合は 0 に置き換え(int型に変換)
merged["val2"] = merged["val2"].fillna(0).astype(int)

# 出力
merged.to_csv("ans.csv", index=False, header=False)
print("ans.csv を出力しました。")

一般的なデータ処理するプログラムならアルゴリズムとかライブラリの使い方を知らなくてもプログラムが書けちゃいますね。。。ほんと。

プログラムとして入力ー処理ー出力のテストパターンで要求仕様を表現すれば機能が作れそうです。

チーム開発とかする必要ってもう無くなるのかもなぁ。。。極端な話。