fork(1) download
  1. # Use complement negation for mixed sign addition. (6)
  2. # @see GA5Sy6
  3.  
  4. import itertools
  5. import operator
  6. import random
  7.  
  8. class Num:
  9. base = 2**8
  10.  
  11. def __init__(self, init=0):
  12. if isinstance(init, tuple):
  13. self.m = init[0].copy()
  14. self.s = init[1]
  15. else:
  16. self.m = iton(abs(init), Num.base)
  17. self.s = init < 0
  18.  
  19. def __neg__(self):
  20. return Num((self.m, not self.s))
  21.  
  22. def __add__(self, other):
  23. return Num(nadd(self.m, self.s, other.m, other.s, Num.base))
  24.  
  25. def __sub__(self, other):
  26. t = _fixsign(other.m, not other.s)[1]
  27. return Num(nadd(self.m, self.s, other.m, t, Num.base))
  28.  
  29. def __mul__(self, other):
  30. return Num(nmul(self.m, self.s, other.m, other.s, Num.base))
  31.  
  32. def __str__(self):
  33. return '-' * self.s + ntos(self.m, Num.base)
  34.  
  35. def __repr__(self):
  36. return str((self.m, self.s))
  37.  
  38. # Utility.
  39.  
  40. def _iszero(a):
  41. return len(a) == 1 and a[0] == 0
  42.  
  43. def _fixsign(a, s):
  44. return a, s and not _iszero(a)
  45.  
  46. def _zeroextend(a, n):
  47. return a[:] + [0] * (n - len(a))
  48.  
  49. def _zeroreduce(a):
  50. n = len(a)
  51. while n != 1 and a[n-1] == 0:
  52. n -= 1
  53. return a[:n]
  54.  
  55. def _inplace_addc(r, a, c, b):
  56. for i in range(len(r)):
  57. c, r[i] = divmod(r[i] + a[i] + c, b)
  58. return c, r
  59.  
  60. def _inplace_mulc(r, x, c, b):
  61. for i in range(len(r)):
  62. c, r[i] = divmod(r[i] * x + c, b)
  63. return c, r
  64.  
  65. def _complement(a, b):
  66. return [b-1-x for x in a]
  67.  
  68. def _negate(a, b):
  69. return _inplace_addc(_complement(a, b), _zeroextend([1], len(a)), 0, b)[1]
  70.  
  71. # Convert.
  72.  
  73. def iton(x, b):
  74. r = []
  75. while True:
  76. x, y = divmod(x, b)
  77. r.append(y)
  78. if x == 0:
  79. return r
  80.  
  81. def nton(a, bi, bo):
  82. r = [0]
  83. for x in reversed(a):
  84. c = _inplace_mulc(r, bi, x, bo)[0]
  85. if c != 0:
  86. r.extend(iton(c, bo))
  87. return r
  88.  
  89. def ntos(a, b):
  90. return ''.join(map(str, reversed(nton(a, b, 10))))
  91.  
  92. # Compare.
  93.  
  94. def _cmp(x, y):
  95. if x != y:
  96. return -1 if x < y else 1
  97. return 0
  98.  
  99. def ncmp(a, b):
  100. n = len(a)
  101. m = len(b)
  102. u = itertools.chain([n], reversed(a))
  103. v = itertools.chain([m], reversed(b))
  104. return next(itertools.dropwhile(lambda x: x == 0, map(_cmp, u, v)), 0)
  105.  
  106. # Shift.
  107.  
  108. def nshl(a, n):
  109. return _zeroreduce([0] * n + a[:])
  110.  
  111. def nshr(a, n):
  112. return _zeroextend(a[n:], 1)
  113.  
  114. # Add.
  115.  
  116. def _add(a, b, base):
  117. n = 1 + max(len(a), len(b))
  118. a = _zeroextend(a, n)
  119. b = _zeroextend(b, n)
  120. return _zeroreduce(_inplace_addc(a, b, 0, base)[1])
  121.  
  122. def nadd(a, s, b, t, base):
  123. if s == t:
  124. return _fixsign(_add(a, b, base), s)
  125. if s:
  126. a, b = b, a
  127. a = _zeroextend(a, len(b))
  128. b = _zeroextend(b, len(a))
  129. c, r = _inplace_addc(a, _negate(b, base), 0, base)
  130. if not c:
  131. r = _negate(r, base)
  132. return _fixsign(_zeroreduce(r), not c)
  133.  
  134. # Multiply.
  135.  
  136. def _mul1(a, x, base):
  137. n = 1 + len(a)
  138. return _zeroreduce(_inplace_mulc(_zeroextend(a, n), x, 0, base)[1])
  139.  
  140. def _mul(a, b, base):
  141. if _iszero(b):
  142. return [0]
  143. return _add(_mul1(a, b[0], base), _mul(nshl(a, 1), nshr(b, 1), base),
  144. base)
  145.  
  146. def nmul(a, s, b, t, base):
  147. return _fixsign(_mul(a, b, base), s != t)
  148.  
  149. # Test.
  150.  
  151. def _test(n, op):
  152. w = Num.base
  153. z = (0, 1, -1, w, -w, w-1, 1-w)
  154. for x, y in itertools.product(z, repeat=2):
  155. u = int(str(op(Num(x), Num(y))))
  156. v = op(x, y)
  157. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  158. w = Num.base ** 3
  159. for _ in range(n):
  160. x = random.randint(-w, w)
  161. y = random.randint(-w, w)
  162. u = int(str(op(Num(x), Num(y))))
  163. v = op(x, y)
  164. assert u == v, f'{op}({x}, {y})\nExpected:{v}, Got:{u}'
  165.  
  166. n = 1000
  167. _test(n, operator.add)
  168. _test(n, operator.sub)
  169. _test(n, operator.mul)
  170.  
  171. def show1(a):
  172. print(repr(a), a, sep='; ')
  173.  
  174. def _show(z, op):
  175. print(op)
  176. for x, y in itertools.product(z, repeat=2):
  177. show1(op(Num(x), Num(y)))
  178.  
  179. w = Num.base
  180. z = (0, 1, -1, w, -w)
  181. _show(z, operator.add)
  182. _show(z, operator.sub)
  183. _show(z, operator.mul)
  184.  
  185. def factorial(n):
  186. r = Num(1)
  187. for i in range(2, n+1):
  188. r *= Num(i)
  189. return r
  190.  
  191. print(factorial)
  192. for i in range(5):
  193. show1(factorial(10*i))
Success #stdin #stdout 0.14s 9968KB
stdin
Standard input is empty
stdout
<built-in function add>
([0], False); 0
([1], False); 1
([1], True); -1
([0, 1], False); 256
([0, 1], True); -256
([1], False); 1
([2], False); 2
([0], False); 0
([1, 1], False); 257
([255], True); -255
([1], True); -1
([0], False); 0
([2], True); -2
([255], False); 255
([1, 1], True); -257
([0, 1], False); 256
([1, 1], False); 257
([255], False); 255
([0, 2], False); 512
([0], False); 0
([0, 1], True); -256
([255], True); -255
([1, 1], True); -257
([0], False); 0
([0, 2], True); -512
<built-in function sub>
([0], False); 0
([1], True); -1
([1], False); 1
([0, 1], True); -256
([0, 1], False); 256
([1], False); 1
([0], False); 0
([2], False); 2
([255], True); -255
([1, 1], False); 257
([1], True); -1
([2], True); -2
([0], False); 0
([1, 1], True); -257
([255], False); 255
([0, 1], False); 256
([255], False); 255
([1, 1], False); 257
([0], False); 0
([0, 2], False); 512
([0, 1], True); -256
([1, 1], True); -257
([255], True); -255
([0, 2], True); -512
([0], False); 0
<built-in function mul>
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([0], False); 0
([1], False); 1
([1], True); -1
([0, 1], False); 256
([0, 1], True); -256
([0], False); 0
([1], True); -1
([1], False); 1
([0, 1], True); -256
([0, 1], False); 256
([0], False); 0
([0, 1], False); 256
([0, 1], True); -256
([0, 0, 1], False); 65536
([0, 0, 1], True); -65536
([0], False); 0
([0, 1], True); -256
([0, 1], False); 256
([0, 0, 1], True); -65536
([0, 0, 1], False); 65536
<function factorial at 0x14b9901918b0>
([1], False); 1
([0, 95, 55], False); 3628800
([0, 0, 180, 130, 124, 103, 195, 33], False); 2432902008176640000
([0, 0, 0, 84, 221, 245, 93, 134, 150, 15, 55, 246, 19, 13], False); 265252859812191058636308480000000
([0, 0, 0, 0, 64, 37, 5, 255, 100, 222, 15, 8, 126, 242, 199, 132, 27, 232, 234, 142], False); 815915283247897734345611269596115894272000000000