Karatsuba
Fast multiplication algorithm, developed by
Anatoly Karatsuba at the age of 23!

TABLE = {}
for i in range(10):
for j in range(10):
TABLE[(i, j)] = i * j
HALF_TABLE = []
for i in range(100):
HALF_TABLE.append(i // 2)
def strpad(str, n, padding='left', chr='0'):
if padding == 'left':
return n * chr + str
return str + n * chr
def karatsuba(x, y):
assert isinstance(x, int), 'x must be integer'
assert isinstance(y, int), 'y must be integer'
if x < 10 and y < 10:
return TABLE[(x, y)]
x = str(x)
y = str(y)
if len(x) < len(y): x = strpad(x, len(y) - len(x), 'left')
if len(y) < len(x): y = strpad(y, len(x) - len(y), 'left')
m = HALF_TABLE[len(x)]
a, b = int(x[:m]), int(x[m:])
c, d = int(y[:m]), int(y[m:])
k1 = karatsuba(a, c)
k2 = karatsuba(b, d)
k3 = karatsuba(a + b, c + d)
k4 = k3 - k2 - k1
k1 = strpad(str(k1), (len(x) - m) + (len(x) - m), 'right')
k4 = strpad(str(k4), (len(x) - m), 'right')
return int(k1) + int(k4) + int(k2)
def linear_product(x, y):
product = 0
for _ in range(x):
product += y
return product
def native_product(x, y):
return x * y
assert karatsuba(10, 20) == 200
assert karatsuba(90, 900) == 81000
assert karatsuba(1357, 2468) == 3349076
import time
x = 123_456_789
y = 123_456_789
t0 = time.time()
p1 = karatsuba(x, y); t1 = time.time() - t0
t0 = time.time()
p2 = linear_product(x, y); t2 = time.time() - t0
t0 = time.time()
p3 = native_product(x, y); t3 = time.time() - t0
assert p1 == p2
print("karatsuba()", t1, "s")
print("linear_product()", t2, "s")
print("native_product()", t3, "s")