diff --git a/python/e024.py b/python/e024.py index 5b5ceee..4596989 100644 --- a/python/e024.py +++ b/python/e024.py @@ -1,29 +1,26 @@ -from itertools import permutations +from lib_misc import permutations def euler_024_library(): + from itertools import permutations return int("".join(list(permutations("0123456789"))[1000000 - 1])) -def permutations_(iterable): - if not iterable: - yield iterable - for i in range(len(iterable)): - elem = iterable[i:i + 1] - rest = iterable[:i] + iterable[i + 1:] - for ps in permutations_(rest): - yield elem + ps - - -def n_th(generator, n): +def nth(generator, n): for i in range(n): next(generator) return next(generator) +def nth_permutation(iterable, n): + """ Returns the nth permutation of the iterable. """ + # XXX: Implement this! + return 0 + + def euler_024(): - g = permutations_("0123456789") - return int(n_th(g, 1000000 - 1)) + g = permutations("0123456789") + return int(nth(g, 1000000 - 1)) if __name__ == "__main__": diff --git a/python/e027.py b/python/e027.py index a741e5b..3498ea8 100644 --- a/python/e027.py +++ b/python/e027.py @@ -1,56 +1,27 @@ -def get_primes_till(n): - square = lambda n: n * n - candiates = range(2, n + 1) - primes = [] - while candiates: - prime = candiates[0] - primes.append(prime) - candiates = [c for c in candiates if c % prime != 0] - return primes +from lib_prime import primes, is_prime -def get_coprime(n): - primes = get_primes_till(n) - for p in primes: - if n % p != 0: - return p - raise Exception("No coprime found for {}.".format(n)) - -def is_prime_fermat(n): - if n == 2: - return True - a = get_coprime(n) - if (a ** (n - 1) % n) != 1: - return False - else: - return True - -def is_prime_deterministic(n): - pass - -def is_prime(n): - if n == 2: - return True - if n < 2: - return False - if not is_prime_fermat(n): - return False - else: - return True - return is_prime_deterministic(n) - -def get_length(a, b): +def number_consecutive_primes(a, b): def formula(n): - return n*n + a*n + b - for n in range(99999): + return n * n + a * n + b + n = 0 + while True: if not is_prime(formula(n)): return n + n += 1 -def bruteforce(): - solution = None - options = [(get_length(a, b), a, b) - for a in get_primes_till(1000) - for b in get_primes_till(1000)] - print(max(options)) -bruteforce() +def euler_027(): + n_max, a_max, b_max = 0, 0, 0 + for b in primes(1000): + for a in range(-999, 1000): + a = -1 * a + n = number_consecutive_primes(a, b) + if n > n_max: + n_max, a_max, b_max = n, a, b + return a_max * b_max + + +if __name__ == "__main__": + print("e027.py: {}".format(euler_027())) + assert(euler_027() == -59231) diff --git a/python/e028.py b/python/e028.py new file mode 100644 index 0000000..6cc490d --- /dev/null +++ b/python/e028.py @@ -0,0 +1,12 @@ +def euler_028(): + total = 1 + current_corner = 3 + for n in range(3, 1002, 2): + total += 4 * current_corner + 6 * (n - 1) + current_corner += 4 * n - 2 + return total + + +if __name__ == "__main__": + print("e028.py: {}".format(euler_028())) + assert(euler_028() == 669171001) diff --git a/python/e029.py b/python/e029.py new file mode 100644 index 0000000..b12c6dd --- /dev/null +++ b/python/e029.py @@ -0,0 +1,7 @@ +def euler_029(): + return len(set([a**b for a in range(2, 101) for b in range(2, 101)])) + + +if __name__ == "__main__": + print("e029.py: {}".format(euler_029())) + assert(euler_029() == 9183) diff --git a/python/e030.py b/python/e030.py new file mode 100644 index 0000000..3f3410d --- /dev/null +++ b/python/e030.py @@ -0,0 +1,13 @@ +def euler_030(): + fifth_power_lookup = {str(i): i**5 for i in range(0, 10)} + + def is_number_sum_of_fiths_powers_of_digits(n): + return n == sum([fifth_power_lookup[d] for d in str(n)]) + + return sum([i for i in range(2, 1000000) + if is_number_sum_of_fiths_powers_of_digits(i)]) + + +if __name__ == "__main__": + print("e030.py: {}".format(euler_030())) + assert(euler_030() == 443839) diff --git a/python/e031.py b/python/e031.py new file mode 100644 index 0000000..57ddf1e --- /dev/null +++ b/python/e031.py @@ -0,0 +1,23 @@ +def count_change(change, coins): + from math import ceil + count = 0 + coin, coins = coins[0], coins[1:] + + if change % coin == 0: + count += 1 + + if not coins: + return count + + for i in range(ceil(change / coin)): + count += count_change(change - i * coin, coins) + return count + + +def euler_031(): + return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1]) + + +if __name__ == "__main__": + print("e031.py: {}".format(euler_031())) + assert(euler_031() == 73682) diff --git a/python/e032.py b/python/e032.py new file mode 100644 index 0000000..1ae48ad --- /dev/null +++ b/python/e032.py @@ -0,0 +1,23 @@ +from lib_misc import permutations + + +def is_solution(s): + a, b, c = int(s[0:2]), int(s[2:5]), int(s[5:]) + if a * b == c: + return c + a, b, c = int(s[0:1]), int(s[1:5]), int(s[5:]) + if a * b == c: + return c + return 0 + + +def euler_032(): + return sum(set([is_solution("".join(p)) + for p in permutations("123456789")])) + + +if __name__ == "__main__": + assert(is_solution("391867254") == 7254) + assert(is_solution("391867245") == 0) + print("e032.py: {}".format(euler_032())) + assert(euler_032() == 45228) diff --git a/python/e033.py b/python/e033.py new file mode 100644 index 0000000..ba002b3 --- /dev/null +++ b/python/e033.py @@ -0,0 +1,38 @@ +from lib_misc import gcd + + +def is_curious(n, d): + assert(len(str(n)) == 2 and len(str(d)) == 2) + if n == d: + return False + for i in range(1, 10): + if str(i) in str(n) and str(i) in str(d): + try: + n_ = int(str(n).replace(str(i), "")) + d_ = int(str(d).replace(str(i), "")) + except ValueError: + return False + try: + if n_ / d_ == n / d: + return True + except ZeroDivisionError: + return False + return False + + +def euler_033(): + fs = [(n, d) for n in range(10, 100) + for d in range(n, 100) if is_curious(n, d)] + n = 1 + d = 1 + for n_, d_ in fs: + n *= n_ + d *= d_ + return d // gcd(n, d) + + +if __name__ == "__main__": + assert(is_curious(49, 98) is True) + assert(is_curious(30, 50) is False) + print("e033.py: {}".format(euler_033())) + assert(euler_033() == 100) diff --git a/python/e034.py b/python/e034.py new file mode 100644 index 0000000..1792a3d --- /dev/null +++ b/python/e034.py @@ -0,0 +1,26 @@ +from lib_misc import factorial + + +def is_curious(n): + s = sum([factorial(int(d)) for d in str(n)]) + return n == s + + +def is_curious_faster(n): + """ Potentially faster solution. """ + s = 0 + for d in str(n): + s += factorial(int(d)) + if s > n: + return False + return n == s + + +def euler_034(): + return sum([n for n in range(3, 10**5) if is_curious(n)]) + + +if __name__ == "__main__": + assert(is_curious(145)) + print("e034.py: {}".format(euler_034())) + assert(euler_034() == 40730) diff --git a/python/e035.py b/python/e035.py new file mode 100644 index 0000000..a706830 --- /dev/null +++ b/python/e035.py @@ -0,0 +1,25 @@ +from lib_prime import primes + + +def cyles(xs): + if len(xs) <= 1: + return xs + return [xs[i:] + xs[:i] for i in range(len(xs))] + + +def is_circular(p, prime_set): + cs = cyles(str(p)) + for c in cs: + if not int("".join(c)) in prime_set: + return False + return True + + +def euler_035(): + ps = set(primes(1000000)) + return len([p for p in ps if is_circular(p, ps)]) + + +if __name__ == "__main__": + print("e035.py: {}".format(euler_035())) + assert(euler_035() == 55) diff --git a/python/lib_misc.py b/python/lib_misc.py index d232d79..dd81b27 100644 --- a/python/lib_misc.py +++ b/python/lib_misc.py @@ -136,9 +136,10 @@ def collatz_sequence_length(n): @lru_cache(maxsize=10000) def factorial(n): - if n == 1: - return 1 - return n * factorial(n - 1) + p = 1 + for i in range(1, n + 1): + p *= i + return p def proper_divisors(n): @@ -177,3 +178,25 @@ def sum_proper_divisors(n): s += q d += 1 return s + + +def permutations(iterable): + """ + Generator that returns all permutations for the iterable. + + Generates equivalent result to itertools.permutations. + """ + if not iterable: + yield iterable + for i in range(len(iterable)): + elem = iterable[i:i + 1] + rest = iterable[:i] + iterable[i + 1:] + for ps in permutations(rest): + yield elem + ps + + +def gcd(a, b): + """ Returns the greatest commond divisor of a and b. """ + if b == 0: + return a + return gcd(b, a % b) diff --git a/python/lib_misc_tests.py b/python/lib_misc_tests.py index 03d02b2..34c2723 100644 --- a/python/lib_misc_tests.py +++ b/python/lib_misc_tests.py @@ -11,6 +11,8 @@ try: from .lib_misc import collatz_sequence_length from .lib_misc import factorial from .lib_misc import proper_divisors, sum_proper_divisors + from .lib_misc import permutations + from .lib_misc import gcd except ModuleNotFoundError: from lib_misc import is_palindrome_integer from lib_misc import is_palindrome_string @@ -23,6 +25,8 @@ except ModuleNotFoundError: from lib_misc import collatz_sequence_length from lib_misc import factorial from lib_misc import proper_divisors, sum_proper_divisors + from lib_misc import permutations + from lib_misc import gcd class TestPrimeMethods(unittest.TestCase): @@ -95,6 +99,38 @@ class TestPrimeMethods(unittest.TestCase): self.assertEqual(sum_proper_divisors(220), 284) self.assertEqual(sum_proper_divisors(284), 220) + def test_permutations(self): + from itertools import permutations as std_permutations + test_list = [] + p1 = list(map(tuple, permutations(test_list))) + p2 = list(std_permutations(test_list)) + self.assertEqual(p1, p2) + + test_list = [1] + p1 = list(map(tuple, permutations(test_list))) + p2 = list(std_permutations(test_list)) + self.assertEqual(p1, p2) + + test_list = [1, 2, 3] + p1 = list(map(tuple, permutations(test_list))) + p2 = list(std_permutations(test_list)) + self.assertEqual(p1, p2) + + test_list = [1, 2, 3, 4, 5, 6] + p1 = list(map(tuple, permutations(test_list))) + p2 = list(std_permutations(test_list)) + self.assertEqual(p1, p2) + + test_list = "abc" + p1 = list(map(tuple, permutations(test_list))) + p2 = list(std_permutations(test_list)) + self.assertEqual(p1, p2) + + def test_gcd(self): + self.assertEqual(gcd(3, 2), 1) + self.assertEqual(gcd(15, 6), 3) + self.assertEqual(gcd(6, 15), 3) + if __name__ == '__main__': unittest.main() diff --git a/python/lib_prime.py b/python/lib_prime.py index fa901d6..66db518 100644 --- a/python/lib_prime.py +++ b/python/lib_prime.py @@ -1,3 +1,4 @@ +from functools import lru_cache try: from lib_misc import get_item_counts from lib_misc import product @@ -43,6 +44,7 @@ def prime_factors_count(n): return get_item_counts(prime_factors(n)) +@lru_cache(maxsize=10000) def is_prime(n): """Returns True if n is prime and False otherwise.