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