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

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

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

Python の例

PythonVisual Studioからインストールしました。PythonイテレーターはC#と同様なので、だいたい同じように書けました。next は next(イテレーターの式) のように書かないといけません。この書き方がバージョンによって違うようでウェブに書いてあるようにやるとうまくできません。

Python のコード

def Align0(xs, leng, z):
    return xs + [z] * (leng - len(xs))

def ZipWith0(z, f, xs, ys):
    xsx = Align0(xs, len(ys), z)
    ysx = Align0(ys, len(xs), z)
    return list(map(lambda cpl: f(cpl[0], cpl[1]), list(zip(xsx, ysx))))

def Iterate(next, init):
    cur = init
    while True:
        yield cur
        cur = next(cur)

def Take(count, seq):
    c = count
    for e in seq:
        if c == 0:
            break
        c -= 1
        yield e

def CarryStep(carry_and_dec, x):
    carry, dec = carry_and_dec
    newdec = LongDecimal([(x + carry) % 10] + dec.decimals, 0)
    return  ((x + carry) // 10, newdec)

from functools import reduce

class LongDecimal:
    def __init__(self, ns, e):
        self.decimals = [0] * e + ns

    def Decimalize(self, c, leave):
        carry, dec = reduce(CarryStep, self.decimals[::-1], (c, LongDecimal([], 0)))
        if leave and carry != 0:
            return dec.Sum(carry * 10)
        else:
            return dec

    def Shift(self, e):
        return LongDecimal(self.decimals, e)

    def Product(self, n):
        if isinstance(n, int):
	        LongDecimal(list(map(lambda yd: n * yd, self.decimals)), 0)

    def CollectShiftMult(self, y):
        e = 0
        for xd in self.decimals:
                yield y.Product(xd).Shift(e)
                e += 1

    def Sum(self, y):
        if isinstance(y, int):
            return LongDecimal([self.decimals[0] + y] + self.decimals[1:], 0)
        else:
            return LongDecimal(ZipWith0(0, lambda a, b: a + b, self.decimals, y.decimals), 0).Decimalize(0, True)

    def Difference(self, y):
        yds = Align0(y.decimals, len(self.decimals), 0)
        return LongDecimal(ZipWith0(0, lambda a, b: a + b, self.decimals,list(map(lambda a: 9 - a, yds))), 0).Decimalize(1, False)

    def Product(self, y):
        if isinstance(y, int):
	        return LongDecimal(list(map(lambda x: x * y, self.decimals)), 0)
        else:
            return reduce(lambda a, b: a.Sum(b), self.CollectShiftMult(y), LongDecimal([], 0))

    def LessOrEqual(self, y):
        equal = all(ZipWith0(0, lambda a, b: a == b, self.decimals, y.decimals))
        if equal:
            return False
        else:
            ne_index = (ZipWith0(0, lambda a, b: a == b, self.decimals, y.decimals)).index(False)
            return (ZipWith0(0, lambda a, b: a < b, self.decimals, y.decimals))[ne_index]

    def Print(self):
        res = ""
        count = 0
        for d in self.decimals:
            if count == 1:
                res += "."
            res += str(d)
            count += 1
        return res

class Numbers:
    def __init__(self, number, square_difference, scale):
        self.current_digit = 0
        self.number = number
        self.square_difference = square_difference
        self.scale = scale
    def CurrentDigit(self):
        return self.current_digit
    def GetNextDecimalDigit(self):
        two = LongDecimal([2], 0)
        self.current_digit = -1
        for dd in range(9, -1, -1):
            if self.current_digit < 0:
                zd = LongDecimal([dd], self.scale)
                number_sq_diff = self.number.Product(zd).Product(two).Sum(zd.Product(zd))
                if number_sq_diff.LessOrEqual(self.square_difference):
                    self.number = self.number.Sum(zd)
                    self.square_difference = self.square_difference.Difference(number_sq_diff)
                    self.scale += 1
                    self.current_digit = dd
        return self.current_digit

class NumbersGenerator:
    def __init__(self):
        self.generator = self.GenerateDecimal()
    def GetNextDecimalDigit(self):
        return next(self.generator)
    def GenerateDecimal(self):
        number = LongDecimal([], 0)
        square_difference = LongDecimal([3], 0)
        nums = Numbers(number, square_difference, 0)
        while True:
            yield nums.GetNextDecimalDigit()

class NumbersServer:
    def __init__(self):
        self.current_numbers = Numbers(LongDecimal([], 0), LongDecimal([], 0), 0)
        self.generator_server = self.GenerateDecimalServer()
    def GetNumbers(self):
        return next(self.generator_server)
    def SetNumbers(self, numbers):
        self.current_numbers = numbers
    def GenerateDecimalServer(self):
        number = LongDecimal([], 0)
        square_difference = LongDecimal([3], 0)
        current_numbers = Numbers(number, square_difference, 0)
        while True:
            yield current_numbers

class Calc:
    def __init__(self):
        self.count = 21
        self.generator = NumbersGenerator()
        self.generator_server = NumbersServer()
        self.result_number = LongDecimal([], 0)
    def RepeatGenerator(self):
        for e in range(self.count):
            zd = LongDecimal([self.generator.GetNextDecimalDigit()], e)
            self.result_number = self.result_number.Sum(zd)
        return self.result_number.Print()
    def RepeatServer(self):
        for e in range(self.count):
            numbers = self.generator_server.GetNumbers()
            dd = numbers.GetNextDecimalDigit()
            self.generator_server.SetNumbers(numbers)
            self.result_number = self.result_number.Sum(LongDecimal([dd], e))
        return self.result_number.Print()
    def IterateGenerator(self):
        dec = list(Take(self.count, self.generator.GenerateDecimal()))
        return LongDecimal(dec, 0).Print()
    def IterateServer(self):
        number = LongDecimal([], 0)
        square_difference = LongDecimal([3], 0)
        init_numbers = Numbers(number, square_difference, 0)
        init_numbers.GetNextDecimalDigit()
        dec = list(Take(self.count, map(lambda numbers: numbers.CurrentDigit(), Iterate(NextNumbers, init_numbers))))
        return LongDecimal(dec, 0).Print()

def NextNumbers(numbers):
    numbers.GetNextDecimalDigit()
    return numbers

print(Calc().RepeatGenerator())
print(Calc().RepeatServer())
print(Calc().IterateGenerator())
print(Calc().IterateServer())