import time
from interchangeable import interchangeable

def naive_intersection(lista,listb):
    intersection = []
    for element in lista:
        if element in listb:
            intersection.append(element)
    return intersection

def set_intersection(lista,listb):
    return list(set(lista).intersection(set(listb)))

if __name__ == "__main__":
    intersection = interchangeable(naive_intersection, set_intersection)
    start = time.time()
    intersection.learning = True
    for i in range(350):
        intersection(range(i),range(i*2))
    print "learning took ", time.time() - start, " seconds"
    intersection.learning = False
    start = time.time()
    for i in range(350):
        intersection(range(i),range(i*2))
    choosing_time = time.time() - start
    print "choosing took ", choosing_time, " seconds"
    start = time.time()
    for i in range(350):
        naive_intersection(range(i),range(i*2))
    print "naive took ", (time.time() - start) - choosing_time, " more seconds than choosing"
    start = time.time()
def fib_recursive(n):
    if n == 0 or n == 1:
        return 1
    return fib_recursive(n-1) + fib_recursive(n-2)

def fib_dynamic(n):
    arr = [0,1]
    while len(arr) < n + 1:
        arr.append(arr[-1] + arr[-2])
    return arr[n]

def fib_closed_form(n):
    return int(round(1/(sqrt(5))*((1+sqrt(5))/2)**n - (1/(sqrt(5))*((1-sqrt(5))/2)**n)))
    
if __name__ == "__main__":
    fib = interchangeable(fib_closed_form, fib_dynamic)
    start = time.time()
    fib.learning = True
    for i in range(350):
        print fib(i)
    print "took ", time.time() - start, " seconds"
    fib.learning = False
    start = time.time()
    for i in range(350):
        print fib(i)
    choosing_time = time.time() - start
    print "choosing took ", choosing_time, " seconds"
    start = time.time()
    for i in range(350):
        fib_dynamic(i)
    print "fib_dyanmic took ", (time.time() - start) - choosing_time, " more seconds than choosing"
    if p > 3500:
        break


def pre_calculate_prime_factors(n):
    if n in ps:
        return [n]
    l = []
    for p in ps:
        if n % p == 0:
            l.append(p)
    return l


if __name__ == "__main__":
    prime_factors = interchangeable(naive_prime_factors, pre_calculate_prime_factors)
    start = time.time()
    prime_factors.learning = True
    for i in range(3500):
        print i
        prime_factors(i)
    print "learning took ", time.time() - start, " seconds"
    prime_factors.learning = False
    start = time.time()
    for i in range(3500):
        prime_factors(i)
    choosing_time = time.time() - start
    print "choosing took ", time.time() - start, " seconds"
    start = time.time()
    for i in range(3500):
        pre_calculate_prime_factors(i)
        if i == lena:
            ret.append(b[j])
            j += 1
        elif j == lenb:
            ret.append(a[i])
            i += 1
        elif a[i] <= b[j]:
            ret.append(a[i])
            i += 1
        else:
            ret.append(b[j])
            j += 1
    return ret

if __name__ == "__main__":
    merge = interchangeable(naive_merge, merge_sort_merge, triple_sort_merge)
    start = time.time()
    merge.learning = True
    for i in range(350):
        a = range(i*10)
        b = range(i,351)
        random.shuffle(a)
        random.shuffle(b)
        merge(a,b)
    print "learning took ", time.time() - start, " seconds"
    merge.learning = False
    start = time.time()
    for i in range(350):
        a = range(i*10)
        b = range(i,351)
        random.shuffle(a)