|
|
|
from __future__ import division, print_function
|
|
|
|
|
|
|
|
from functools import update_wrapper, wraps
|
|
|
|
import json
|
|
|
|
import operator
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
class HashableDict(dict):
|
|
|
|
|
|
|
|
def __hash__(self):
|
|
|
|
return hash(tuple(sorted(self.items())))
|
|
|
|
|
|
|
|
|
|
|
|
def json_memoize(filename):
|
|
|
|
"""A decorator that memoizes function calls in a JSON file."""
|
|
|
|
|
|
|
|
class JsonMemoize:
|
|
|
|
|
|
|
|
def __init__(self, fn):
|
|
|
|
self.fn = fn
|
|
|
|
update_wrapper(self, fn)
|
|
|
|
|
|
|
|
if not os.path.exists(filename):
|
|
|
|
with open(filename, "w") as f:
|
|
|
|
json.dump({}, f)
|
|
|
|
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
|
|
with open(filename, "r") as f:
|
|
|
|
memo = json.load(f)
|
|
|
|
json_key = repr((self.fn.__name__, args, HashableDict(kwargs)))
|
|
|
|
if json_key not in memo:
|
|
|
|
memo[json_key] = self.fn(*args, **kwargs)
|
|
|
|
with open(filename, "w") as f:
|
|
|
|
json.dump(memo, f,
|
|
|
|
indent=4,
|
|
|
|
separators=(',', ': '),
|
|
|
|
sort_keys=True)
|
|
|
|
f.write("\n")
|
|
|
|
return memo[json_key]
|
|
|
|
|
|
|
|
return JsonMemoize
|
|
|
|
|
|
|
|
|
|
|
|
def timed(f):
|
|
|
|
"""Return a timed version of function f.
|
|
|
|
|
|
|
|
The returned function returns a tuple of (time, real return value)
|
|
|
|
|
|
|
|
:param f: function to time
|
|
|
|
"""
|
|
|
|
|
|
|
|
@wraps(f)
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
import time
|
|
|
|
|
|
|
|
time_start = time.time()
|
|
|
|
return_ = f(*args, **kwargs)
|
|
|
|
time_end = time.time()
|
|
|
|
time_delta = time_end - time_start
|
|
|
|
return time_delta, return_
|
|
|
|
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
@json_memoize('json_memoize_tmp.json')
|
|
|
|
def is_prime(n):
|
|
|
|
"""Really inefficiently check if n is a prime number."""
|
|
|
|
if n == 0 or n == 1:
|
|
|
|
return False
|
|
|
|
|
|
|
|
for i in xrange(2, n):
|
|
|
|
if n % i == 0:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
@json_memoize('json_memoize_tmp.json')
|
|
|
|
def multiply(*args):
|
|
|
|
"""Multiply all args."""
|
|
|
|
return reduce(operator.mul, args, 1)
|
|
|
|
|
|
|
|
|
|
|
|
@json_memoize('json_memoize_tmp.json')
|
|
|
|
def some_with_kwargs(one, two, **kwargs):
|
|
|
|
"""Add 'one' and 'two' and all the values of the keyword arguments."""
|
|
|
|
return one + two + reduce(operator.add, [kwargs[k] for k in kwargs], 0)
|
|
|
|
|
|
|
|
|
|
|
|
assert(is_prime(0) is False)
|
|
|
|
assert(is_prime(1) is False)
|
|
|
|
assert(is_prime(2) is True)
|
|
|
|
assert(is_prime(2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10) is False)
|
|
|
|
|
|
|
|
is_prime_timed = timed(is_prime)
|
|
|
|
for c in range(1, 11):
|
|
|
|
time, result = is_prime_timed(86028157)
|
|
|
|
assert (result is True)
|
|
|
|
print("Call {}: {:.2f}s".format(c, time))
|
|
|
|
|
|
|
|
assert(multiply(1, 2, 3, 4) == 24)
|
|
|
|
assert(multiply(1, 2, 3, 4, 5) == 120)
|
|
|
|
|
|
|
|
assert(some_with_kwargs(1, 2, three=3, four=4) == 10)
|