diff --git a/README.markdown b/README.markdown index e46009f..4acd65f 100644 --- a/README.markdown +++ b/README.markdown @@ -42,13 +42,14 @@ Should be used in order to help future reuse of code :) 28 - What is the sum of both diagonals in a 1001 by 1001 spiral? - < 1 sec
29 - How many distinct terms are in the sequence generated by ab for 2 a 100 and 2 b 100? - < 1 sec
30 - Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. - < 3 sec
-34 - Find the sum of all numbers which are equal to the sum of the factorial of their digits. - 30 sec
+34 - Find the sum of all numbers which are equal to the sum of the factorial of their digits. - 30 sec - 16 sec
36 - Find the sum of all numbers less than one million, which are palindromic in base 10 and base 2. - 0.933
39 - If p is the perimeter of a right angle triangle, {a, b, c}, which value, for p <= 1000, has the most solutions? - 1min
42 - Using words.txt, a 16K text file containing nearly two-thousand common English words, how many are triangle words? - < 1 sec
45 - Find the next triangle number that is also pentagonal and hexagonal. - < 1 sec
48 - Find the last ten digits of 1^1 + 2^2 + ... + 1000^1000. - 0.053
52 - Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits. - 2min
+53 - How many values of C(n,r), for 1 <= n <= 100, exceed one-million? - < 1 sec
67 - Using an efficient algorithm find the maximal sum in the triangle? - 0.027
**In progress: ** @@ -56,7 +57,7 @@ Should be used in order to help future reuse of code :) 26 - Find the value of d < 1000 for which 1/d contains the longest recurring cycle.
31 - Investigating combinations of English currency denominations.
35 - How many circular primes are there below one million?
-53 - How many values of C(n,r), for 1 <= n <= 100, exceed one-million?
+97 - Find the last ten digits of the non-Mersenne prime: 28433 × 2^7830457 + 1. **WARNING : Spoil inside for those who want to solve problems by themselves :)** diff --git a/e_2.py b/e_2.py old mode 100755 new mode 100644 index 1bd356b..2228c0e --- a/e_2.py +++ b/e_2.py @@ -33,8 +33,6 @@ def even_sum_fib(max_value): return fib_sum - - if __name__ == '__main__': val = 4000000 print "Answer : %d " % (even_sum_fib(val)) diff --git a/e_34_2.py b/e_34_2.py new file mode 100644 index 0000000..25b8bbb --- /dev/null +++ b/e_34_2.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +''' +Created on 8 feb. 2012 + +@author: Julien Lengrand-Lambert + +DESCRIPTION: Solves problem 34 of Project Euler +145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. + +Find the sum of all numbers which are equal to the sum of the factorial of their digits. + +Note: as 1! = 1 and 2! = 2 are not sums they are not included. +''' +import timeit +from utils.memoize import memoize + +def find_limit(): + """ + Returns the max number of digits we have to loop through to find the solution + """ + nb_digits = 2 + max_num = fact(9) * nb_digits + + while len(str(max_num)) >= nb_digits: + nb_digits += 1 + + return nb_digits - 1 + +@memoize +def fact(value): + """ + Returns value! + """ + if value == 0: + return 1 + return value * fact(value - 1) + +def digsum(num): + """ + Returns the sum of factorial of digits of num + ex : digsum(123, 4) = fact(1) + fact(2) + fact(3) + """ + val = 0 + for el in str(num): + val += fact(int(el)) + + return val + +def sum_fact2(): + """ + Finds the sum of all the numbers that can be written as the sum of the factorial of their digits. + """ + max_dig = find_limit() + max_val = fact(9) * max_dig + print "Max dig is : %d" %(max_dig) + sumf = 0 + + cpt = 3 + while cpt <= max_val: + if cpt == digsum(cpt): + sumf += cpt + + cpt +=1 + + return sumf + +if __name__ == '__main__': + # The major problem in there is to find the upper limit. + t2 = timeit.Timer("sum_fact2()", "from __main__ import sum_fact2") + print t2.timeit(1) diff --git a/e_35.py b/e_35.py index 8287388..06ed339 100644 --- a/e_35.py +++ b/e_35.py @@ -52,39 +52,7 @@ def prime_list(max_val): cur += 1 return plist - -def perm_primes_old(max_val): - """ - Returns the number of circular primes below max_val - """ - circulars = 0 - circl = [] - - # to avoid calculating primes - # plist = pickle.load(open("primes_list.dup", "rb")) - # print plist - plist = prime_list(max_val) - print "###" - # stuff here - cpt = 0 - for prime in plist: - cpt += 1 - print "%d/%d" % ( cpt, len(plist)) - print circulars, circl - perms = all_permutations(str(prime)) # finds all permutations - - # counts how many permutations are in prime list given one prime - p_cpt = 0 - for perm in perms: - if int(perm) in plist: - p_cpt += 1 - # if prime is circular - if p_cpt == len(perms): - circulars += 1 - circl.append(prime) - - return circulars, circl def perm_primes(max_val): """ @@ -128,5 +96,4 @@ def perm_primes(max_val): if __name__ == '__main__' : answer, plist = perm_primes(1000000) - print "Answer is : %d" % (answer) - print plist \ No newline at end of file + print "Answer is : %d" % (answer) \ No newline at end of file diff --git a/e_53.py b/e_53.py index 8c23ac1..f85ae7a 100644 --- a/e_53.py +++ b/e_53.py @@ -13,16 +13,42 @@ In combinatorics, we use the notation, 5C3 = 10. In general, -nCr = n! / r!(nr)! ,where r n, n! = n(n1)...321, and 0! = 1. +nCr = n! / r!(n - r)! ,where r <= n, n! = n * (n - 1) * ... * 3 * 2 * 1, and 0! = 1. It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066. -How many, not necessarily distinct, values of nCr, for 1 n 100, are greater than one-million? +How many, not necessarily distinct, values of nCr, for 1 <= n <= 100, are greater than one-million? ''' -def aaa(): +from utils.memoize import memoize + +@memoize +def fact(value): """ - Returns + Returns value! """ - return 1 + if value == 0: + return 1 + return value * fact(value - 1) + +def comb(n, r): + """ + Returns nCr = n! / r!(n - r)!,where r <= n + """ + if r > n : + raise ValueError("n should be >= r !") + else: + return (fact(n) / (fact(r) * fact(n - r))) + +def upper_comb(max_n, val): + """ + Returns the number of values of nCr, for 1 <= n <= max_n that are greater than value? + """ + nb = 0 + for ns in range(1, max_n + 1): + for nr in range(1, ns + 1): + if comb(ns, nr) > val: + nb += 1 + + return nb if __name__ == '__main__': - print "Answer : %d " % (1) + print "Answer : %d " % (upper_comb(100, 1000000)) \ No newline at end of file diff --git a/e_97.py b/e_97.py new file mode 100644 index 0000000..9c30bb1 --- /dev/null +++ b/e_97.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +''' +Created on 10 feb. 2012 + +@author: Julien Lengrand-Lambert + +DESCRIPTION: Solves problem 31 of Project Euler +The first known prime found to exceed one million digits was discovered in 1999, and is a Mersenne prime of the form 2^6972593 - 1. +it contains exactly 2,098,960 digits. Subsequently other Mersenne primes, of the form 2^p - 1, have been found which contain more digits. + +However, in 2004 there was found a massive non-Mersenne prime which contains 2,357,207 digits: 28433 * 2^7830457 + 1. + +Find the last ten digits of this prime number. +''' +def last_ten(): + """ + Returns the last ten digits of 28433 * 2^7830457 + 1 + """ + val = 28433 * pow(2, 7830457) + 1 + return str(val)[-10:] + +if __name__ == '__main__': + #print "Answer : %d " % (last_ten()) + print pow(2, 7830457) diff --git a/utils/Memoized.py b/utils/Memoized.py new file mode 100644 index 0000000..88fbd44 --- /dev/null +++ b/utils/Memoized.py @@ -0,0 +1,34 @@ +''' +Created on + +@author: airballman +@contact: julien@lengrand.fr +''' +import functools + +class Memoized(object): + """ + Decorator that caches a function's return value each time it is called. + If called later with the same arguments, the cached value is returned, and + not re-evaluated. + """ + def __init__(self, func): + self.func = func + self.cache = {} + def __call__(self, *args): + try: + return self.cache[args] + except KeyError: + value = self.func(*args) + self.cache[args] = value + return value + except TypeError: + # uncachable -- for instance, passing a list as an argument. + # Better to not cache than to blow up entirely. + return self.func(*args) + def __repr__(self): + """Return the function's docstring.""" + return self.func.__doc__ + def __get__(self, obj, objtype): + """Support instance methods.""" + return functools.partial(self.__call__, obj) \ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..728add3 --- /dev/null +++ b/utils/__init__.py @@ -0,0 +1,6 @@ +''' +Created on + +@author: airballman +@contact: julien@lengrand.fr +''' diff --git a/utils/fact_memoization.py b/utils/fact_memoization.py new file mode 100644 index 0000000..4763036 --- /dev/null +++ b/utils/fact_memoization.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +''' +Created on 17 feb. 2012 + +@author: Julien Lengrand-Lambert +@contact: julien@lengrand.fr +''' +import timeit +from memoize import memoize +from Memoized import Memoized + +def fact1(value): + """ + Returns value! + """ + if value == 0: + return 1 + return value * fact1(value - 1) + +@memoize +def fact2(value): + """ + Returns value!, using memoization + """ + if value == 0: + return 1 + return value * fact2(value - 1) + +@Memoized +def fact3(value): + """ + Returns value!, using memoization + """ + if value == 0: + return 1 + return value * fact3(value - 1) + +if __name__ == '__main__': + for i in range(3): + t1 = timeit.Timer("fact1(150)", "from __main__ import fact1") + t2 = timeit.Timer("fact2(150)", "from __main__ import fact2") + t3 = timeit.Timer("fact3(150)", "from __main__ import fact3") + print t1.timeit(1), t2.timeit(1), t3.timeit(1) \ No newline at end of file diff --git a/utils/fib_memoization.py b/utils/fib_memoization.py new file mode 100644 index 0000000..b53cb97 --- /dev/null +++ b/utils/fib_memoization.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +''' +Created on 17 feb. 2012 + +@author: Julien Lengrand-Lambert +@contact: julien@lengrand.fr +''' +import timeit +from memoize import memoize +from Memoized import Memoized + +def fib1(n): + """Returns the n st value of Fibonnacci list""" + if n < 2: + return n + else: + return fib1(n-1) + fib1(n - 2) + +@memoize +def fib2(n): + """Returns the n st value of Fibonnacci list, using memoization""" + if n < 2: + return n + else: + return fib2(n-1) + fib2(n - 2) + +@Memoized +def fib3(n): + """Returns the n st value of Fibonnacci list, using memoization""" + if n < 2: + return n + else: + return fib3(n-1) + fib3(n - 2) + +if __name__ == '__main__': + for i in range(3): + t1 = timeit.Timer("fib1(20)", "from __main__ import fib1") + t2 = timeit.Timer("fib2(20)", "from __main__ import fib2") + t3 = timeit.Timer("fib3(20)", "from __main__ import fib3") + print t1.timeit(1), t2.timeit(1), t3.timeit(1) \ No newline at end of file diff --git a/utils/memoize.py b/utils/memoize.py new file mode 100644 index 0000000..4f14993 --- /dev/null +++ b/utils/memoize.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +''' +Created on 17 feb. 2012 + +@author: Julien Lengrand-Lambert +@contact: julien@lengrand.fr +''' + +def memoize(function): + """Defines a memoization scheme""" + cache = {} + def decorated_function(*args): + if args in cache: + return cache[args] + else: + val = function(*args) + cache[args] = val + return val + return decorated_function \ No newline at end of file