# (3)
# @see 6SDvDi
import operator
class Num:
def __init__(self, init=0):
self.s = init < 0
self.m = iton(abs(init))
def __neg__(self):
self.s = not self.s
return self
def __add__(self, other):
self.m, self.s = nadd(self.m, self.s, other.m, other.s)
return self
def __sub__(self, other):
self.m, self.s = nadd(self.m, self.s, other.m, not other.s)
return self
def __mul__(self, other):
self.m, self.s = nmul(self.m, self.s, other.m, other.s)
return self
def __str__(self):
return '-' * self.s + ntos(self.m)
def __repr__(self):
return str(self.s) + ':' + str(self.m)
# Utility.
def _iszero(a):
return len(a) == 1 and a[0] == 0
def _fixsign(a, s):
return a, False if _iszero(a) else s
def _zeroextend(a, n):
return a[:] + [0] * (n - len(a))
def _zeroreduce(a):
n = len(a)
while n != 1 and a[n-1] == 0:
n -= 1
return a[:n]
# Conversion.
def iton(x):
r = []
while True:
x, y = divmod(x, 10)
r.append(y)
if x == 0:
return r
def ntos(a):
return ''.join(map(str, reversed(a)))
# Compare.
def _cmp(x, y):
if x != y:
return -1 if x < y else 1
return 0
def ncmp(a, b):
n = len(a)
m = len(b)
if n != m:
return _cmp(n, m)
for x, y in zip(reversed(a), reversed(b)):
if x != y:
return _cmp(x, y)
return 0
# Shift.
def nshl(a, n):
return _zeroreduce([0] * n + a[:])
def nshr(a, n):
return _zeroextend(a[n:], 1)
# Add.
def _add(a, b, op):
n = 1 + max(len(a), len(b))
r = _zeroextend(a, n)
b = _zeroextend(b, n)
c = 0
for i in range(n):
c, r[i] = divmod(op(r[i], b[i] + abs(c)), 10)
return _zeroreduce(r)
def nadd(a, s, b, t):
if s == t:
return _fixsign(_add(a, b, operator.add), s)
elif ncmp(a, b) < 0:
return _fixsign(_add(b, a, operator.sub), t)
else:
return _fixsign(_add(a, b, operator.sub), s)
# Multiply.
def _mul1(a, x):
assert 0 <= x < 10
n = 1 + len(a)
r = _zeroextend(a, n)
c = 0
for i in range(n):
c, r[i] = divmod(r[i] * x + c, 10)
return _zeroreduce(r)
def _mul(a, b):
if _iszero(b):
return [0]
return _add(_mul1(a, b[0]), _mul(nshl(a, 1), nshr(b, 1)), operator.add)
def nmul(a, s, b, t):
return _fixsign(_mul(a, b), s != t)
# Test.
n = 50
for x in range(-n, n+1):
for y in range(-n, n+1):
# nadd
u = int(str(Num(x) + Num(y)))
v = x + y
assert u == v, f'{x} + {y}; {u}, {v}'
# nmul
u = int(str(Num(x) * Num(y)))
v = x * y
assert u == v, f'{x} * {y}; {u}, {v}'
def show(a):
print(repr(a), a, sep='; ')
x = 123
show(Num( 0))
show(Num( 1))
show(Num(-1))
show(Num( x))
show(Num(-x))
print('+')
show(Num(0) + Num(0))
show(Num(0) + Num(1))
show(Num(1) + Num(0))
show(Num(1) + Num(x))
show(Num(x) + Num(1))
show(Num(x) + Num(x))
print('-')
show(Num(0) - Num(0))
show(Num(0) - Num(1))
show(Num(1) - Num(0))
show(Num(1) - Num(x))
show(Num(x) - Num(1))
show(Num(x) - Num(x))
print('*')
show(Num(0) * Num(0))
show(Num(0) * Num(1))
show(Num(1) * Num(0))
show(Num(1) * Num(x))
show(Num(x) * Num(1))
show(Num(x) *-Num(1))
show(Num(x) * Num(x))
show(Num(x) *-Num(x))
IyAoMykKIyBAc2VlIDZTRHZEaQoKaW1wb3J0IG9wZXJhdG9yCgpjbGFzcyBOdW06CiAgICBkZWYgX19pbml0X18oc2VsZiwgaW5pdD0wKToKICAgICAgICBzZWxmLnMgPSBpbml0IDwgMAogICAgICAgIHNlbGYubSA9IGl0b24oYWJzKGluaXQpKQoKICAgIGRlZiBfX25lZ19fKHNlbGYpOgogICAgICAgIHNlbGYucyA9IG5vdCBzZWxmLnMKICAgICAgICByZXR1cm4gc2VsZgoKICAgIGRlZiBfX2FkZF9fKHNlbGYsIG90aGVyKToKICAgICAgICBzZWxmLm0sIHNlbGYucyA9IG5hZGQoc2VsZi5tLCBzZWxmLnMsIG90aGVyLm0sIG90aGVyLnMpCiAgICAgICAgcmV0dXJuIHNlbGYKCiAgICBkZWYgX19zdWJfXyhzZWxmLCBvdGhlcik6CiAgICAgICAgc2VsZi5tLCBzZWxmLnMgPSBuYWRkKHNlbGYubSwgc2VsZi5zLCBvdGhlci5tLCBub3Qgb3RoZXIucykKICAgICAgICByZXR1cm4gc2VsZgoKICAgIGRlZiBfX211bF9fKHNlbGYsIG90aGVyKToKICAgICAgICBzZWxmLm0sIHNlbGYucyA9IG5tdWwoc2VsZi5tLCBzZWxmLnMsIG90aGVyLm0sIG90aGVyLnMpCiAgICAgICAgcmV0dXJuIHNlbGYKCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gJy0nICogc2VsZi5zICsgbnRvcyhzZWxmLm0pCgogICAgZGVmIF9fcmVwcl9fKHNlbGYpOgogICAgICAgIHJldHVybiBzdHIoc2VsZi5zKSArICc6JyArIHN0cihzZWxmLm0pCgojIFV0aWxpdHkuCgpkZWYgX2lzemVybyhhKToKICAgIHJldHVybiBsZW4oYSkgPT0gMSBhbmQgYVswXSA9PSAwCgpkZWYgX2ZpeHNpZ24oYSwgcyk6CiAgICByZXR1cm4gYSwgRmFsc2UgaWYgX2lzemVybyhhKSBlbHNlIHMKCmRlZiBfemVyb2V4dGVuZChhLCBuKToKICAgIHJldHVybiBhWzpdICsgWzBdICogKG4gLSBsZW4oYSkpCgpkZWYgX3plcm9yZWR1Y2UoYSk6CiAgICBuID0gbGVuKGEpCiAgICB3aGlsZSBuICE9IDEgYW5kIGFbbi0xXSA9PSAwOgogICAgICAgIG4gLT0gMQogICAgcmV0dXJuIGFbOm5dCgojIENvbnZlcnNpb24uCgpkZWYgaXRvbih4KToKICAgIHIgPSBbXQogICAgd2hpbGUgVHJ1ZToKICAgICAgICB4LCB5ID0gZGl2bW9kKHgsIDEwKQogICAgICAgIHIuYXBwZW5kKHkpCiAgICAgICAgaWYgeCA9PSAwOgogICAgICAgICAgICByZXR1cm4gcgoKZGVmIG50b3MoYSk6CiAgICByZXR1cm4gJycuam9pbihtYXAoc3RyLCByZXZlcnNlZChhKSkpCgojIENvbXBhcmUuCgpkZWYgX2NtcCh4LCB5KToKICAgIGlmIHggIT0geToKICAgICAgICByZXR1cm4gLTEgaWYgeCA8IHkgZWxzZSAxCiAgICByZXR1cm4gMAoKZGVmIG5jbXAoYSwgYik6CiAgICBuID0gbGVuKGEpCiAgICBtID0gbGVuKGIpCiAgICBpZiBuICE9IG06CiAgICAgICAgcmV0dXJuIF9jbXAobiwgbSkKICAgIGZvciB4LCB5IGluIHppcChyZXZlcnNlZChhKSwgcmV2ZXJzZWQoYikpOgogICAgICAgIGlmIHggIT0geToKICAgICAgICAgICAgcmV0dXJuIF9jbXAoeCwgeSkKICAgIHJldHVybiAwCgojIFNoaWZ0LgoKZGVmIG5zaGwoYSwgbik6CiAgICByZXR1cm4gX3plcm9yZWR1Y2UoWzBdICogbiArIGFbOl0pCgpkZWYgbnNocihhLCBuKToKICAgIHJldHVybiBfemVyb2V4dGVuZChhW246XSwgMSkKCiMgQWRkLgoKZGVmIF9hZGQoYSwgYiwgb3ApOgogICAgbiA9IDEgKyBtYXgobGVuKGEpLCBsZW4oYikpCiAgICByID0gX3plcm9leHRlbmQoYSwgbikKICAgIGIgPSBfemVyb2V4dGVuZChiLCBuKQogICAgYyA9IDAKICAgIGZvciBpIGluIHJhbmdlKG4pOgogICAgICAgIGMsIHJbaV0gPSBkaXZtb2Qob3AocltpXSwgYltpXSArIGFicyhjKSksIDEwKQogICAgcmV0dXJuIF96ZXJvcmVkdWNlKHIpCgpkZWYgbmFkZChhLCBzLCBiLCB0KToKICAgIGlmIHMgPT0gdDoKICAgICAgICByZXR1cm4gX2ZpeHNpZ24oX2FkZChhLCBiLCBvcGVyYXRvci5hZGQpLCBzKQogICAgZWxpZiBuY21wKGEsIGIpIDwgMDoKICAgICAgICByZXR1cm4gX2ZpeHNpZ24oX2FkZChiLCBhLCBvcGVyYXRvci5zdWIpLCB0KQogICAgZWxzZToKICAgICAgICByZXR1cm4gX2ZpeHNpZ24oX2FkZChhLCBiLCBvcGVyYXRvci5zdWIpLCBzKQoKIyBNdWx0aXBseS4KCmRlZiBfbXVsMShhLCB4KToKICAgIGFzc2VydCAwIDw9IHggPCAxMAogICAgbiA9IDEgKyBsZW4oYSkKICAgIHIgPSBfemVyb2V4dGVuZChhLCBuKQogICAgYyA9IDAKICAgIGZvciBpIGluIHJhbmdlKG4pOgogICAgICAgIGMsIHJbaV0gPSBkaXZtb2QocltpXSAqIHggKyBjLCAxMCkKICAgIHJldHVybiBfemVyb3JlZHVjZShyKQoKZGVmIF9tdWwoYSwgYik6CiAgICBpZiBfaXN6ZXJvKGIpOgogICAgICAgIHJldHVybiBbMF0KICAgIHJldHVybiBfYWRkKF9tdWwxKGEsIGJbMF0pLCBfbXVsKG5zaGwoYSwgMSksIG5zaHIoYiwgMSkpLCBvcGVyYXRvci5hZGQpCgpkZWYgbm11bChhLCBzLCBiLCB0KToKICAgIHJldHVybiBfZml4c2lnbihfbXVsKGEsIGIpLCBzICE9IHQpCgojIFRlc3QuCgpuID0gNTAKZm9yIHggaW4gcmFuZ2UoLW4sIG4rMSk6CiAgICBmb3IgeSBpbiByYW5nZSgtbiwgbisxKToKICAgICAgICAjIG5hZGQKICAgICAgICB1ID0gaW50KHN0cihOdW0oeCkgKyBOdW0oeSkpKQogICAgICAgIHYgPSB4ICsgeQogICAgICAgIGFzc2VydCB1ID09IHYsIGYne3h9ICsge3l9OyB7dX0sIHt2fScKICAgICAgICAjIG5tdWwKICAgICAgICB1ID0gaW50KHN0cihOdW0oeCkgKiBOdW0oeSkpKQogICAgICAgIHYgPSB4ICogeQogICAgICAgIGFzc2VydCB1ID09IHYsIGYne3h9ICoge3l9OyB7dX0sIHt2fScKCmRlZiBzaG93KGEpOgogICAgcHJpbnQocmVwcihhKSwgYSwgc2VwPSc7ICcpCgp4ID0gMTIzCnNob3coTnVtKCAwKSkKc2hvdyhOdW0oIDEpKQpzaG93KE51bSgtMSkpCnNob3coTnVtKCB4KSkKc2hvdyhOdW0oLXgpKQpwcmludCgnKycpCnNob3coTnVtKDApICsgTnVtKDApKQpzaG93KE51bSgwKSArIE51bSgxKSkKc2hvdyhOdW0oMSkgKyBOdW0oMCkpCnNob3coTnVtKDEpICsgTnVtKHgpKQpzaG93KE51bSh4KSArIE51bSgxKSkKc2hvdyhOdW0oeCkgKyBOdW0oeCkpCnByaW50KCctJykKc2hvdyhOdW0oMCkgLSBOdW0oMCkpCnNob3coTnVtKDApIC0gTnVtKDEpKQpzaG93KE51bSgxKSAtIE51bSgwKSkKc2hvdyhOdW0oMSkgLSBOdW0oeCkpCnNob3coTnVtKHgpIC0gTnVtKDEpKQpzaG93KE51bSh4KSAtIE51bSh4KSkKcHJpbnQoJyonKQpzaG93KE51bSgwKSAqIE51bSgwKSkKc2hvdyhOdW0oMCkgKiBOdW0oMSkpCnNob3coTnVtKDEpICogTnVtKDApKQpzaG93KE51bSgxKSAqIE51bSh4KSkKc2hvdyhOdW0oeCkgKiBOdW0oMSkpCnNob3coTnVtKHgpICotTnVtKDEpKQpzaG93KE51bSh4KSAqIE51bSh4KSkKc2hvdyhOdW0oeCkgKi1OdW0oeCkp