import time def timeit(func): '''A simple wrapper to measure execution time''' def wrapper(*args, **kwargs): timer = time.time() rslt = func(*args, **kwargs) timer = time.time() - timer print(timer) return wrapper def source(): for k in range(1,100000): yield (1+k)*k//2 def make_pairs(src): buffer = None for chunk in src: if buffer: yield buffer, chunk buffer = None else: buffer = chunk def split(src): for chunk in src: yield chunk yield chunk def multiply(src): for x,y in src: yield x*y def gcd(src): def helper(x, y): if x < y: yield from helper(y, x) elif y == 0: yield x else: yield from helper(y, x%y) for x,y in src: yield from helper(x,y) def combine(src1, src2): for x in src1: yield x, next(src2) def divide(src): for x,y in src: yield x//y def get_digits(src): def helper(x): if x != 0: yield from helper(x//10) yield x%10 for x in src: yield from helper(x) def sink(src): for chunk in src: pass def pipeline(): s = split(make_pairs(source())) sink(get_digits(divide(combine(multiply(s), gcd(s))))) def repeat(): for i in range(100): pipeline() timeit(repeat)()