ChatGPTでマルチ言語

Table of Contents

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も、これに便乗してるのさ。整数にするなんて、めっそうも無い事と刻み こまれているんだな。

etc