エレファント・ビジュアライザー調査記録

ビジュアルプログラミングで数式の変形を表すことを考えていくブロクです。

人工知能的サーバー対ブラウザー(5)

今回は ChatGPT で Python から F# に書き換えたのですが、これはそのままでは動かなくて、かなり書き直しました。

このプログラムの mutable な変数を mutable ではないものに変更するとどうなるか、ということを考えたいのですが、これはなかなか難しそうです。以前このブログで取り上げたときも、とくに何もできていませんでした。今回も同じことになりそうなので、ブログに書く意味があるのか、と思いますがいちおう ChatGPT をちょっと使ったということで書いておくことにします。

open System
open System.Collections.Generic

let formatDecimal (dec: int seq) =
    let declist: int list = Seq.toList dec
    let head = declist.Head
    let tail = declist.Tail |> List.map string |> String.concat ""
    sprintf "%d.%s" head tail

// decimal 型に対するべき乗演算子
let rec ( ** ) (d: decimal) (exp: int) = 
    if exp = 0 then
        1M
    elif exp > 0 then
        d ** (exp - 1) * d
    else
        d ** (exp + 1) / d

// 数値クラスの定義
type Numbers(number: decimal, squareDifference: decimal, scale: int) =
    let mutable number = number
    let mutable squareDifference = squareDifference
    let mutable scale = scale
    member _.Copy() = Numbers(number, squareDifference, scale)
    member _.GetNextDecimalDigit() =
        let two = decimal 2
        Seq.head (seq {
            for dd in [9..-1..0] do
                let zd = decimal dd * (decimal 10 ** -scale)
                let numberSqDiff = number * zd * two + zd * zd
                if numberSqDiff <= squareDifference then
                    number <- number + zd
                    squareDifference <- squareDifference - numberSqDiff
                    scale <- scale + 1
                    yield dd
            })

// 数値ジェネレータークラス
type NumbersGenerator() =
    let generator =
        let number = decimal 0
        let squareDifference = decimal 3
        let nums = Numbers(number, squareDifference, 0)
        seq { while true do yield nums.GetNextDecimalDigit() }
    member _.GetNextDecimalDigit() =
        generator |> Seq.head
    member _.GenerateDecimal() =
        generator

// 数値サーバークラス
type NumbersServer() =
    let mutable currentNumbers =
        Numbers(decimal 0, decimal 3, 0)
    let generatorServer =
        Seq.unfold (fun n -> Some(n, n)) currentNumbers
    member _.GetNumbers() = currentNumbers
    member _.SetNumbers(numbers: Numbers) =
        currentNumbers <- numbers

// 計算クラス
type Calc() =
    let count = 21
    let generator = NumbersGenerator()
    let generatorServer = NumbersServer()
    let mutable resultNumber = decimal 0
    
    member _.RepeatGenerator() =
        for e in [0 .. count - 1] do
            let zd = (decimal (generator.GetNextDecimalDigit())) / (10M ** e)
            resultNumber <- resultNumber + zd
        resultNumber.ToString()

    member _.RepeatServer() =
        for e in [0 .. count - 1] do
            let numbers = generatorServer.GetNumbers()
            let dd = numbers.GetNextDecimalDigit()
            generatorServer.SetNumbers(numbers)
            resultNumber <- resultNumber + (decimal dd) / (10M ** e)
        resultNumber.ToString()

    member _.IterateGenerator() =
        let dec = Seq.take count (generator.GenerateDecimal())
        formatDecimal dec

    member _.IterateServer() =
        let initialNumbers = Numbers(decimal 0, decimal 3, 0)
        let dec = Seq.take count (Seq.unfold (fun (n: Numbers) -> let nn = n.Copy() in Some(nn.GetNextDecimalDigit(), nn)) initialNumbers)
        formatDecimal dec

// テスト出力
printfn "%s" (Calc().RepeatGenerator())
printfn "%s" (Calc().RepeatServer())
printfn "%s" (Calc().IterateGenerator())
printfn "%s" (Calc().IterateServer())