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