ChatGPTでマルチ言語
gen many lang
前回やった詩人の言語作成能力は、まったく未熟で、どうしようもないので、 流暢に多言語をしゃべるであろうChatGPTに再び登場願おう。
ただ流暢だねと感嘆するのが目的じゃなくて、別の思惑があるんだ。 仕様は、前回作成したものを流用する。
使う言語のバージョンを細かく指定してたんで、文句を言われるかと思ったら、 そこは無視いや寛容であった。ただ、作成したコードは、スケルトンだからね、 と、下記の警告が添えられたよ。
このコードは、指定された仕様に基づいて動作する基本的な骨組みを提供します。ただし、入力データの検証やエラーハンドリング、統計データの計算と表示など、いくつかの重要な部分は実装されていません。これらの部分を適切に実装することで、プログラムが正しく動作するようになります。
これは、宿題をコピペですまそうとする輩に苦慮した、文部科学省からの提案に、 OpenAIのCEOが忖度したものと思われる。何と言っても、日本はお得意様です からね。今月の日経Linuxでも、特集が組まれている。先取りするのが、もう けのこつ。後から日本産のAIが出てきても、牙城は切り崩せないわな。
golang
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"
)
const (
maxDataCount = 70
fileName = "test.csv"
)
type Measurement struct {
Timestamp time.Time
Hi int
Lo int
Pl int
}
func main() {
args := os.Args[1:]
if len(args) > 0 && (args[0] == "-h" || args[0] == "--help") {
printHelp()
return
}
if len(args) > 0 && args[0] == "-ire" && len(args) > 1 {
inputAndRegisterData(args[1])
}
displayStatistics()
}
func printHelp() {
fmt.Println("Usage: bps [-h] [-ire yymm[dd]]")
fmt.Println(" bps -h : Display this help message")
fmt.Println(" bps -ire yymm[dd] : Input and register data interactively")
}
func inputAndRegisterData(inputDate string) {
fmt.Printf("%s> ", inputDate)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line := scanner.Text()
if line == "fin" {
break
}
parts := strings.Fields(line)
if len(parts) != 4 {
fmt.Println("must be [d]dhh hi lo pl")
continue
}
ddhh, err := strconv.Atoi(parts[0])
if err != nil || ddhh < 1 || ddhh > 3123 {
fmt.Println("Invalid ddhh format")
continue
}
hi, err := strconv.Atoi(parts[1])
if err != nil || hi < 80 || hi > 180 {
fmt.Println("Invalid hi range")
continue
}
lo, err := strconv.Atoi(parts[2])
if err != nil || lo < 50 || lo > 110 {
fmt.Println("Invalid lo range")
continue
}
pl, err := strconv.Atoi(parts[3])
if err != nil || pl < 40 || pl > 120 {
fmt.Println("Invalid pl range")
continue
}
timestamp := generateTimestamp(inputDate, ddhh)
measurement := Measurement{Timestamp: timestamp, Hi: hi, Lo: lo, Pl: pl}
registerMeasurement(measurement)
fmt.Printf("%s> ", inputDate)
}
fmt.Println("append", len(data), "data's in", fileName)
}
func generateTimestamp(yymm string, ddhh int) time.Time {
year, _ := strconv.Atoi("20" + yymm[:2])
month, _ := strconv.Atoi(yymm[2:4])
day := ddhh / 100
hour := ddhh % 100
return time.Date(year, time.Month(month), day, hour, 0, 0, 0, time.UTC)
}
var data []Measurement
func registerMeasurement(measurement Measurement) {
data = append(data, measurement)
sort.Slice(data, func(i, j int) bool {
return data[i].Timestamp.Before(data[j].Timestamp)
})
saveToFile()
}
func saveToFile() {
file, err := os.Create(fileName)
if err != nil {
fmt.Println("Error saving data:", err)
return
}
defer file.Close()
for _, measurement := range data {
line := fmt.Sprintf("%s,%d,%d,%d\n", measurement.Timestamp.Format("06010215"), measurement.Hi, measurement.Lo, measurement.Pl)
_, err := file.WriteString(line)
if err != nil {
fmt.Println("Error writing to file:", err)
return
}
}
}
func displayStatistics() {
// Implement the statistics display logic here
fmt.Println("Statistics display not implemented yet")
}
python
import os
import sys
import time
import csv
MAX_DATA_COUNT = 70
FILE_NAME = "test.csv"
class Measurement:
def __init__(self, timestamp, hi, lo, pl):
self.timestamp = timestamp
self.hi = hi
self.lo = lo
self.pl = pl
def print_help():
print("Usage: bps [-h] [-ire yymm[dd]]")
print(" bps -h : Display this help message")
print(" bps -ire yymm[dd] : Input and register data interactively")
def generate_timestamp(yymm, ddhh):
year = 2000 + int(yymm[:2])
month = int(yymm[2:4])
day = ddhh // 100
hour = ddhh % 100
return time.datetime(year, month, day, hour, 0, 0)
def register_measurement(measurement):
data.append(measurement)
data.sort(key=lambda x: x.timestamp)
save_to_file()
def save_to_file():
with open(FILE_NAME, "w", newline="") as file:
writer = csv.writer(file)
for measurement in data:
writer.writerow([measurement.timestamp.strftime("%y%m%d%H"), measurement.hi, measurement.lo, measurement.pl])
def input_and_register_data(input_date):
print(f"{input_date}> ", end="")
for line in sys.stdin:
line = line.strip()
if line == "fin":
break
parts = line.split()
if len(parts) != 4:
print("must be [d]dhh hi lo pl")
continue
try:
ddhh = int(parts[0])
if not 1 <= ddhh <= 3123:
raise ValueError
hi = int(parts[1])
if not 80 <= hi <= 180:
raise ValueError
lo = int(parts[2])
if not 50 <= lo <= 110:
raise ValueError
pl = int(parts[3])
if not 40 <= pl <= 120:
raise ValueError
except ValueError:
print("Invalid input format or range")
continue
timestamp = generate_timestamp(input_date, ddhh)
measurement = Measurement(timestamp, hi, lo, pl)
register_measurement(measurement)
print(f"{input_date}> ", end="")
print(f"append {len(data)} data's in {FILE_NAME}")
def display_statistics():
# Implement the statistics display logic here
print("Statistics display not implemented yet")
def main():
args = sys.argv[1:]
if args and (args[0] == "-h" or args[0] == "--help"):
print_help()
return
if args and args[0] == "-ire" and len(args) > 1:
input_and_register_data(args[1])
display_statistics()
if __name__ == "__main__":
data = []
main()
haskell
import Data.List (sort)
import Data.Time
data Measurement = Measurement
{ timestamp :: UTCTime
, hi :: Int
, lo :: Int
, pl :: Int
}
fileName :: String
fileName = "test.csv"
maxDataCount :: Int
maxDataCount = 70
printHelp :: IO ()
printHelp = do
putStrLn "Usage: bps [-h] [-ire yymm[dd]]"
putStrLn " bps -h : Display this help message"
putStrLn " bps -ire yymm[dd] : Input and register data interactively"
generateTimestamp :: String -> Int -> UTCTime
generateTimestamp yymm ddhh = UTCTime day time
where
year = read $ "20" ++ take 2 yymm
month = read $ drop 2 yymm
day = fromGregorian year month (fromIntegral $ ddhh `div` 100)
time = secondsToDiffTime $ fromIntegral $ (ddhh `mod` 100) * 3600
registerMeasurement :: Measurement -> [Measurement] -> [Measurement]
registerMeasurement measurement measurements =
sort (measurement : measurements)
saveToFile :: [Measurement] -> IO ()
saveToFile measurements = writeFile fileName content
where
content = unlines $ map formatMeasurement measurements
formatMeasurement (Measurement ts hi lo pl) =
formatTime defaultTimeLocale "%y%m%d%H" ts ++ "," ++ show hi ++ "," ++ show lo ++ "," ++ show pl
inputAndRegisterData :: String -> IO ()
inputAndRegisterData inputDate = do
putStr $ inputDate ++ "> "
inputLoop []
where
inputLoop measurements = do
input <- getLine
if input == "fin"
then do
putStrLn $ "append " ++ show (length measurements) ++ " data's in " ++ fileName
saveToFile measurements
else do
let parts = words input
if length parts /= 4
then putStrLn "must be [d]dhh hi lo pl"
else case mapM readMaybe parts of
Just [ddhh, hi, lo, pl] | 1 <= ddhh && ddhh <= 3123 && 80 <= hi && hi <= 180 && 50 <= lo && lo <= 110 && 40 <= pl && pl <= 120 -> do
let timestamp = generateTimestamp inputDate ddhh
measurement = Measurement timestamp hi lo pl
inputLoop $ registerMeasurement measurement measurements
_ -> putStrLn "Invalid input format or range"
displayStatistics :: [Measurement] -> IO ()
displayStatistics measurements = putStrLn "Statistics display not implemented yet"
main :: IO ()
main = do
args <- getArgs
case args of
["-h"] -> printHelp
["-ire", inputDate] -> inputAndRegisterData inputDate
_ -> displayStatistics []
run
そのままで実行できるか、まずはpythonで試行する
[sakae@deb py-bps]$ python3 code.py -ire 2308
0104 120 70 60
2308> Traceback (most recent call last):
File "/FBDEB/meet/py-bps/code.py", line 92, in <module>
main()
File "/FBDEB/meet/py-bps/code.py", line 86, in main
input_and_register_data(args[1])
File "/FBDEB/meet/py-bps/code.py", line 68, in input_and_register_data
timestamp = generate_timestamp(input_date, ddhh)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/FBDEB/meet/py-bps/code.py", line 26, in generate_timestamp
return time.datetime(year, month, day, hour, 0, 0)
^^^^^^^^^^^^^
AttributeError: module 'time' has no attribute 'datetime'. Did you mean: 'asctime'?
pythonの事は、よく知らないのので、頑無視しておく。 golangはどうよ。
[sakae@deb go-bps]$ go run bps.go -ire 2308 2308> 0104 120 60 50 2308> 0121 123 65 55 2308> fin append 2 data's in test.csv Statistics display not implemented yet [sakae@deb go-bps]$ go run bps.go -ire 2308 2308> 1021 131 71 49 2308> fin append 1 data's in test.csv Statistics display not implemented yet [sakae@deb go-bps]$ cat test.csv 23081021,131,71,49
haskellはお約束で、多少のコード追加が必要。
import Text.Read(readMaybe)
import System.Environment(getArgs)
data Measurement = Measurement
{ timestamp :: UTCTime
...
} deriving (Show, Eq, Read, Ord)
ghci> :main -ire 2308 2308> 1004 130 60 55 1021 128 64 59 fin append 2 data's in test.csv
プロンプトの扱かいが多少おかしいですねぇ。
考察
こんなに多言語のコードで、何をする? そう、仮説の検証ね。
AIの頭の中はどうなっている? きっと、コンパイラーみたいな作りになって るだろう。
ユーザーからの自由言語での依頼(様するにソースね)を、一旦扱い易い形式に 変換する。AST相当なものを作るんだな。これが作成できちゃえば、要求によっ て、要約してくださいとか、アイデアを提案してくださいとか、形式言語に変 換してくださいとか、どうとでもなる。
形式言語ってはの、python,golang,haskellと何でもごされだ。場合によって は、自然言語でもいいだろう。英語、中国語、アラビア語と、何でも翻訳でき ちゃう。 対応するモジュールを用意するだけで、自由に追加できる。
そういう目で、上のコードをみると、その言語用に翻訳してるだけじゃん。 きっと、そんな構造になってるんだろうね。
ファイルに追記してくれってお願いしたにもかかわらず、3者共、新規作成に なってる。これは、元の解釈をまちがえたんだな。
もうひとつ例をあげておく。一番大切なデータの持ち方の部分
// for golang
type Measurement struct {
Timestamp time.Time
Hi int
Lo int
Pl int
}
# for python
class Measurement:
def __init__(self, timestamp, hi, lo, pl):
self.timestamp = timestamp
self.hi = hi
self.lo = lo
self.pl = pl
-- for haskell
data Measurement = Measurement
{ timestamp :: UTCTime
, hi :: Int
, lo :: Int
, pl :: Int
}
注目は、測定日の型。オイラーだったら、文字列にするか、整数かのどちらか にする(過去に作成したのは、整数にしてた)んだけどな。なんせ単純な型だか らね。いちいち、それぞれのモジュールを調べる気がしなかったってのが、真 相だ。
コンピュータにとっては、とっても不合理な、暦と時間の扱い。 1月から大の月(31)、小の月(30)と交互にやってくるのに、8月で、そのルールは、く つがえる。昔の王様の横暴。誕生月が、小の月ってのは、許せないとね。 こういう不都合さは、どんな言語を使おうが、つきまとう。ゆえに、不都合さ を緩和するモジュールが(普通は)提供される。
AIも、これに便乗してるのさ。整数にするなんて、めっそうも無い事と刻み こまれているんだな。