エレファント・コンピューティング調査報告

極限に関する順序を論理プログラミングの手法を使って指定することを目指すブロクです。

関数プログラミングと無限論理多項式(13)

Go の例(1)

Go ではクロージャーで実装しました。イテレーターを表すもの(構造体)などを型ごとに複数作っているので長くなります。Goはこのようなプログラムには向いていないようです。xyz は構造体の自分自身を表す名前なのですが self などは使えないようで何が良いのかわからないので xyz になっています。

package main

import (
	"fmt"
	"strconv"
)

type IteratorSimpleImpl_int struct {
	next       func() bool
	getCurrent func() int
	setCurrent func(int)
}

func newIteratorSimpleImpl_int(next func() bool, getCurrent func() int, setCurrent func(int)) *IteratorSimpleImpl_int {
	xyz := new(IteratorSimpleImpl_int)
	xyz.next = next
	xyz.getCurrent = getCurrent
	xyz.setCurrent = setCurrent
	return xyz
}
func (xyz *IteratorSimpleImpl_int) GetCurrent() int {
	return xyz.getCurrent()
}
func (xyz *IteratorSimpleImpl_int) SetCurrent(value int) {
	xyz.setCurrent(value)
}
func (xyz *IteratorSimpleImpl_int) MoveNext() bool {
	return xyz.next()
}
func (xyz *IteratorSimpleImpl_int) Take(count int) []int {
	res := make([]int, count)
	iter := xyz
	for i := 0; i < count && iter.MoveNext(); i++ {
		res[i] = iter.getCurrent()
	}
	return res
}

type IteratorSimpleImpl_Numbers struct {
	next       func() bool
	getCurrent func() *Numbers
	setCurrent func(*Numbers)
}

func newIteratorSimpleImpl_Numbers(next func() bool, getCurrent func() *Numbers, setCurrent func(*Numbers)) *IteratorSimpleImpl_Numbers {
	xyz := new(IteratorSimpleImpl_Numbers)
	xyz.next = next
	xyz.getCurrent = getCurrent
	xyz.setCurrent = setCurrent
	return xyz
}
func (xyz *IteratorSimpleImpl_Numbers) GetCurrent() *Numbers {
	return xyz.getCurrent()
}
func (xyz *IteratorSimpleImpl_Numbers) SetCurrent(value *Numbers) {
	xyz.setCurrent(value)
}
func (xyz *IteratorSimpleImpl_Numbers) MoveNext() bool {
	return xyz.next()
}
func (xyz *IteratorSimpleImpl_Numbers) Take(count int) []*Numbers {
	res := make([]*Numbers, count)
	iter := xyz
	for i := 0; i < count && iter.MoveNext(); i++ {
		res[i] = iter.getCurrent()
	}
	return res
}

func Max(x int, y int) int {
	if x > y {
		return x
	} else {
		return y
	}
}
func Align0(xs []int, leng int, z int) []int {
	m := Max(len(xs), leng)
	res := make([]int, m)
	for i := 0; i < m; i++ {
		if i < len(xs) {
			res[i] = xs[i]
		} else {
			res[i] = z
		}
	}
	return res
}

func ZipWith0_int(z int, f func(int, int) int, xs []int, ys []int) []int {
	xsx := Align0(xs, len(ys), z)
	ysx := Align0(ys, len(xs), z)
	res := make([]int, len(xsx))
	for i := 0; i < len(xsx); i++ {
		res[i] = f(xsx[i], ysx[i])
	}
	return res
}
func ZipWith0_bool(z int, f func(int, int) bool, xs []int, ys []int) []bool {
	xsx := Align0(xs, len(ys), z)
	ysx := Align0(ys, len(xs), z)
	res := make([]bool, len(xsx))
	for i := 0; i < len(xsx); i++ {
		res[i] = f(xsx[i], ysx[i])
	}
	return res
}
func ZipWith0_EqualAndLess(z int, f func(int, int) EqualAndLess, xs []int, ys []int) []EqualAndLess {
	xsx := Align0(xs, len(ys), z)
	ysx := Align0(ys, len(xs), z)
	res := make([]EqualAndLess, len(xsx))
	for i := 0; i < len(xsx); i++ {
		res[i] = f(xsx[i], ysx[i])
	}
	return res
}

func Iterate_Numbers(step func(*Numbers) *Numbers, init *Numbers) *IteratorSimpleImpl_Numbers {
	cur := init
	next := func() bool {
		cur = step(cur)
		return true
	}
	getCurrent := func() *Numbers {
		return cur
	}
	setCurrent := func(val *Numbers) {
	}
	return newIteratorSimpleImpl_Numbers(next, getCurrent, setCurrent)
}
func ShiftR0(ds []int, e int) []int {
	nds := make([]int, e)
	nds = append(nds, ds...)
	return nds
}

func FoldL0(f func(*LongDecimal, *LongDecimal) *LongDecimal, ds []*LongDecimal, z *LongDecimal) *LongDecimal {
	res := z
	for _, d := range ds {
		res = f(res, d)
	}
	return res
}

func FoldR0(f func(CarryAndDec, int) CarryAndDec, ds []int, z CarryAndDec) CarryAndDec {
	res := z
	for i := len(ds) - 1; i >= 0; i-- {
		res = f(res, ds[i])
	}
	return res
}

func Map_int_int(f func(int) int, xs []int) []int {
	res := make([]int, len(xs))
	for i, x := range xs {
		res[i] = f(x)
	}
	return res
}
func Map_Numbers_int(f func(*Numbers) int, xs *IteratorSimpleImpl_Numbers) *IteratorSimpleImpl_int {
	cur := xs
	next := func() bool {
		return cur.next()
	}
	getCurrent := func() int {
		return f(cur.getCurrent())
	}
	setCurrent := func(val int) {
	}
	return newIteratorSimpleImpl_int(next, getCurrent, setCurrent)
}

func Find_EqualAndLess(f func(EqualAndLess) bool, xs []EqualAndLess) EqualAndLess {
	for _, x := range xs {
		if f(x) {
			return x
		}
	}
	return EqualAndLess{false, false}
}
func All(xs []bool) bool {
	for _, x := range xs {
		if !x {
			return false
		}
	}
	return true
}

type CarryAndDec struct {
	carry int
	dec   *LongDecimal
}

type EqualAndLess struct {
	equal bool
	less  bool
}

func Concat(xs []int, ys []int) []int {
	res := xs
	res = append(res, ys...)
	return res
}

func CarryStep(carry_and_dec CarryAndDec, x int) CarryAndDec {
	carry := carry_and_dec.carry
	dec := carry_and_dec.dec
	newdec := newLongDecimal(Concat([]int{(x + carry) % 10}, dec.decimals))
	return CarryAndDec{(x + carry) / 10, newdec}
}

type LongDecimal struct {
	decimals []int
}

func newLongDecimal(ds []int) *LongDecimal {
	xyz := new(LongDecimal)
	xyz.decimals = ds
	return xyz
}
func (xyz *LongDecimal) Decimalize(c int, leave bool) *LongDecimal {
	carry_and_dec := FoldR0(CarryStep, xyz.decimals, CarryAndDec{c, newLongDecimal([]int{})})
	carry := carry_and_dec.carry
	dec := carry_and_dec.dec
	if leave && carry != 0 {
		return dec.Sum1(carry * 10)
	} else {
		return dec
	}
}
func (xyz *LongDecimal) Shift(e int) *LongDecimal {
	return newLongDecimal(ShiftR0(xyz.decimals, e))
}
func (xyz *LongDecimal) CollectShiftMult(y *LongDecimal) []*LongDecimal {
	lds := make([]*LongDecimal, len(xyz.decimals))
	for e, xd := range xyz.decimals {
		lds[e] = y.Product1(xd).Shift(e)
	}
	return lds
}
func (xyz *LongDecimal) Sum1(y int) *LongDecimal {
	ds := Concat([]int{xyz.decimals[0] + y}, xyz.decimals[1:])
	return newLongDecimal(ds)
}
func (xyz *LongDecimal) Sum(y *LongDecimal) *LongDecimal {
	return newLongDecimal(ZipWith0_int(0, func(a, b int) int { return a + b }, xyz.decimals, y.decimals)).Decimalize(0, true)
}
func (xyz *LongDecimal) Difference(y *LongDecimal) *LongDecimal {
	yds := Align0(y.decimals, len(xyz.decimals), 0)
	return newLongDecimal(ZipWith0_int(0, func(a, b int) int { return a + b }, xyz.decimals, Map_int_int(func(a int) int { return 9 - a }, yds))).Decimalize(1, false)
}
func (xyz *LongDecimal) Product1(y int) *LongDecimal {
	return newLongDecimal(Map_int_int(func(x int) int { return x * y }, xyz.decimals))
}
func (xyz *LongDecimal) Product(y *LongDecimal) *LongDecimal {
	return FoldL0(func(a, b *LongDecimal) *LongDecimal { return a.Sum(b) }, xyz.CollectShiftMult(y), newLongDecimal([]int{}))
}
func (xyz *LongDecimal) LessOrEqual(y *LongDecimal) bool {
	equal := All(ZipWith0_bool(0, func(a, b int) bool { return a == b }, xyz.decimals, y.decimals))
	if equal {
		return false
	} else {
		get_eq_and_lt := func(a, b int) EqualAndLess {
			return EqualAndLess{a == b, a < b}
		}
		get_not_eq := func(equal_and_less EqualAndLess) bool {
			return !equal_and_less.equal
		}
		equal_and_less := Find_EqualAndLess(get_not_eq, ZipWith0_EqualAndLess(0, get_eq_and_lt, xyz.decimals, y.decimals))
		return equal_and_less.less
	}
}
func (xyz *LongDecimal) Print() string {
	res := ""
	for count, dd := range xyz.decimals {
		if count == 1 {
			res += "."
		}
		res += strconv.Itoa(dd)
	}
	return res
}

type Numbers struct {
	current_digit     int
	number            *LongDecimal
	square_difference *LongDecimal
	scale             int
}

func newNumbers(number *LongDecimal, square_difference *LongDecimal, scale int) *Numbers {
	xyz := new(Numbers)
	xyz.current_digit = 0
	xyz.number = number
	xyz.square_difference = square_difference
	xyz.scale = scale
	return xyz
}
func (xyz *Numbers) CurrentDigit() int {
	return xyz.current_digit
}
func (xyz *Numbers) GetNextDecimalDigit() int {
	two := newLongDecimal([]int{2})
	for dd := 9; dd >= 0; dd-- {
		zd := newLongDecimal([]int{dd}).Shift(xyz.scale)
		number_sq_diff := xyz.number.Product(zd).Product(two).Sum(zd.Product(zd))
		if number_sq_diff.LessOrEqual(xyz.square_difference) {
			xyz.number = xyz.number.Sum(zd)
			xyz.square_difference = xyz.square_difference.Difference(number_sq_diff)
			xyz.scale++
			xyz.current_digit = dd
			return dd
		}
	}
	return 0
}

type NumbersGenerator struct {
	generator *IteratorSimpleImpl_int
}

func newNumbersGenerator() *NumbersGenerator {
	xyz := new(NumbersGenerator)
	xyz.generator = xyz.GenerateDecimal()
	return xyz
}
func (xyz *NumbersGenerator) GetNextDecimalDigit() int {
	xyz.generator.MoveNext()
	return xyz.generator.GetCurrent()
}
func (xyz *NumbersGenerator) GenerateDecimal() *IteratorSimpleImpl_int {
	number := newLongDecimal([]int{})
	square_difference := newLongDecimal([]int{3})
	nums := newNumbers(number, square_difference, 0)
	current_digit := 0
	next := func() bool {
		current_digit = nums.GetNextDecimalDigit()
		return true
	}
	getCurrent := func() int {
		return current_digit
	}
	setCurrent := func(val int) {
	}
	return newIteratorSimpleImpl_int(next, getCurrent, setCurrent)
}

type NumbersServer struct {
	current_numbers  *Numbers
	generator_server *IteratorSimpleImpl_Numbers
}

func newNumbersServer() *NumbersServer {
	xyz := new(NumbersServer)
	xyz.current_numbers = newNumbers(newLongDecimal([]int{}), newLongDecimal([]int{}), 0)
	xyz.generator_server = xyz.GenerateDecimalServer()
	return xyz
}
func (xyz *NumbersServer) GetNumbers() *Numbers {
	xyz.generator_server.MoveNext()
	return xyz.generator_server.GetCurrent()
}
func (xyz *NumbersServer) SetNumbers(numbers *Numbers) {
	xyz.generator_server.SetCurrent(numbers)
}
func (xyz *NumbersServer) GenerateDecimalServer() *IteratorSimpleImpl_Numbers {
	number := newLongDecimal([]int{})
	square_difference := newLongDecimal([]int{3})
	current_numbers := newNumbers(number, square_difference, 0)
	next := func() bool {
		return true
	}
	getCurrent := func() *Numbers {
		return current_numbers
	}
	setCurrent := func(val *Numbers) {
		current_numbers = val
	}
	return newIteratorSimpleImpl_Numbers(next, getCurrent, setCurrent)
}

type Calc struct {
	count            int
	generator        *NumbersGenerator
	generator_server *NumbersServer
	result_number    *LongDecimal
}

func newCalc() *Calc {
	xyz := new(Calc)
	xyz.count = 21
	xyz.generator = newNumbersGenerator()
	xyz.generator_server = newNumbersServer()
	xyz.result_number = newLongDecimal([]int{})
	return xyz
}
func (xyz *Calc) RepeatGenerator() string {
	for e := 0; e < xyz.count; e++ {
		zd := newLongDecimal([]int{xyz.generator.GetNextDecimalDigit()}).Shift(e)
		xyz.result_number = xyz.result_number.Sum(zd)
	}
	return xyz.result_number.Print()
}
func (xyz *Calc) RepeatServer() string {
	for e := 0; e < xyz.count; e++ {
		numbers := xyz.generator_server.GetNumbers()
		dd := numbers.GetNextDecimalDigit()
		xyz.generator_server.SetNumbers(numbers)
		xyz.result_number = xyz.result_number.Sum(newLongDecimal([]int{dd}).Shift(e))
	}
	return xyz.result_number.Print()
}
func (xyz *Calc) IterateGenerator() string {
	dec := xyz.generator.GenerateDecimal().Take(xyz.count)
	return newLongDecimal(dec).Print()
}
func (xyz *Calc) IterateServer() string {
	number := newLongDecimal([]int{})
	square_difference := newLongDecimal([]int{3})
	init_numbers := newNumbers(number, square_difference, 0)
	dec := Map_Numbers_int(GetCurrentDigit, Iterate_Numbers(NextNumbers, init_numbers)).Take(xyz.count)
	return newLongDecimal(dec).Print()
}

func NextNumbers(numbers *Numbers) *Numbers {
	numbers.GetNextDecimalDigit()
	return numbers
}
func GetCurrentDigit(numbers *Numbers) int {
	return numbers.CurrentDigit()
}

func main() {
	fmt.Printf("%s\n", newCalc().RepeatGenerator())
	fmt.Printf("%s\n", newCalc().RepeatServer())
	fmt.Printf("%s\n", newCalc().IterateGenerator())
	fmt.Printf("%s\n", newCalc().IterateServer())
}