def partition_test():
    from ProjectEuler import partition_slow, partition
    end = 60
    def test1():
        print "partition_slow"
        for i in range(0, end):
            print partition_slow(i)
    def test2():
        print "partition"
        for i in range(0, end):
            print partition(i)
    time_func(test1)
    time_func(test2)
def string_reverse_test():
    from projecteuler import str_reverse

    L = list()
    for i in range(100000):
        L.append(str(i))
    string = "".join(L)

    def test1():
        str_reverse(string)
    time_func(test1)

    def test2():
        string[::-1]
    time_func(test2)

    def str_reverse3(string):
        tmp = list(string)
        tmp.reverse()
        return "".join(tmp)
    def test3():
        str_reverse3(string)
    time_func(test3)
# Project Euler problem 77
# cf. http://blog.dreamshire.com/2009/06/08/project-euler-problem-77-solution/

from pyprimes import primes_below
from projecteuler import time_func


def main():
    primes = list(primes_below(80))
    target = 11  # how many ?
    while True:
        ways = [1] + [0] * target
        for i in primes:
            for j in range(i, target + 1):
                ways[j] += ways[j - i]
        if ways[target] > 5000:
            break
        target += 1
    print target


if __name__ == "__main__":
    time_func(main)
# Project Euler problem 69
# cf. http://d.hatena.ne.jp/tanakaBox/20080516/1210893388

from pyprimes import primes_below
from projecteuler import time_func, totient

def main1():
    primes = list(primes_below(18))
    products = 1
    for prime in primes:
        if products < 1000000:
            products *= prime
        else:
            break
    print products

def main2():
    max_value = 0
    max_n = 0
    for n in xrange(1, 1000001):
        value = n / float(totient(n))
        if max_value < value:
            max_value = value
            max_n = n
    print max_n
        
        

if __name__ == '__main__':
    time_func(main1)
    upperbound = 5000
    prime_nums = [x for x in primes_below(upperbound) if x > lowerbound]
    semiprimes = set()
    for prime1 in prime_nums:
        for prime2 in prime_nums:
            semiprime = prime1 * prime2
            if semiprime < end:
                semiprimes.add(semiprime)
    return semiprimes

def main2():
    semiprimes = create_semiprimes()
    numbers = set() # totient(n) is a permutation of n
    min_value = 100
    min_n = 0
    for semiprime in semiprimes:
        if is_perm(semiprime, totient(semiprime)):
            numbers.add(semiprime)
            
    for num in numbers:
        tmp = num / float(totient(num))
        if tmp < min_value:
            min_value = tmp
            min_n = num
    print min_n
            


if __name__ == '__main__':
    time_func(main2)
        if counter == n:
            break


def gen_digits(n):
    while n:
        yield n % 10
        n /= 10


def square_root(n, l, m=0):
    if l == 0:
        return m

    d = head(dropwhile(lambda d: d * (d + 20 * m) <= n, count(1))) - 1
    n -= d * (d + 20 * m)
    m = m * 10 + d
    return square_root(n * 100, l - 1, m)


def main2():
    N = 100
    M = 100
    print sum(
        map(lambda n: sum(gen_digits(square_root(n, M))),
            filter(lambda n: square_root(n, 1)**2 != n, range(1, N + 1))))


if __name__ == '__main__':
    time_func(main2)
    # project-euler-71-proper-fractions-ascending-order/
    a = 3
    b = 7
    r = 0
    s = 1
    start = 10 ** 6
    for q in xrange(start, 2, -1):
        p = (a * q - 1 ) / b
        if p * s > r * q:
            s = q
            r = p
    print Fraction(r, s)

def main3():
    """Original"""
    target = 10 ** 6
    a, b = 2, 5
    c, d = 3, 7
    while True:
        if b < target:
            #print a, b
            a, b = a + c, b + d
        else:
            a, b = a - c, b - d
            break
    #print Fraction(a, b)
    print a

if __name__ == '__main__':
    time_func(main3)