Remove ipython solutions because the clutter the repository and I like the Python solutions more

main
Felix Martin 2021-04-22 15:08:12 -04:00
parent 5681d3a644
commit 5be3b11e54
142 changed files with 0 additions and 821697 deletions

View File

@ -1,43 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Problem Name (Euler Problem xxx)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": []
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,89 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 1\n",
"\n",
"If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.\n",
"\n",
"Find the sum of all the multiples of 3 or 5 below 1000."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_sum_of_natural_dividable_by_3_and_5_below(m):\n",
" return sum([x for x in range(m) if x % 3 == 0 or x % 5 == 0])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Test example provided in problem statement:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert(get_sum_of_natural_dividable_by_3_and_5_below(10) == 23)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"233168\n"
]
}
],
"source": [
"print(get_sum_of_natural_dividable_by_3_and_5_below(1000))"
]
}
],
"metadata": {
"completion_date": "Tue, 19 Aug 2014, 20:11",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,165 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 2\n",
"\n",
"Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:\n",
"\n",
"1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...\n",
"\n",
"By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def fibonacci_generator():\n",
" a = 0\n",
" b = 1\n",
" while True:\n",
" yield a + b\n",
" a, b = b, (a + b)\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Test fibonacci sequence generator by comparing the result to the example in the task statement."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"i = fibonacci_generator()\n",
"fib_10 = [next(i) for _ in range(10)]\n",
"assert(fib_10 == [1, 2, 3, 5, 8, 13, 21, 34, 55, 89,])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Greate a function which returns all even-valued fibonacci values smaller or equal to four million."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_even_fibonaccis_smaller_or_equal_four_million():\n",
" r = []\n",
" i = fibonacci_generator()\n",
" current_value = next(i)\n",
" while current_value <= 4000000:\n",
" if current_value % 2 == 0:\n",
" r.append(current_value)\n",
" current_value = next(i)\n",
" return r"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Calculate the solution."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4613732\n"
]
}
],
"source": [
"f = get_even_fibonaccis_smaller_or_equal_four_million()\n",
"print(sum(f))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I looked at the solutions in the forum and I kind of forgot about simple straight forward approaches. There is no need to create a list and the sum it up. Instead I can simply increment a counter which will be much faster, but less readable maybe."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4613732\n"
]
}
],
"source": [
"r, a, b = 0, 0, 1\n",
"\n",
"while b <= 4000000:\n",
" if b % 2 == 0:\n",
" r += b\n",
" a, b = b, a + b\n",
" \n",
"print(r)"
]
}
],
"metadata": {
"completion_date": "Tue, 19 Aug 2014, 20:36",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"fibonacci"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,203 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 003\n",
"\n",
"The prime factors of 13195 are 5, 7, 13 and 29.\n",
"\n",
"What is the largest prime factor of the number 600851475143?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start by writing a function which calculates all primes till a certain value using the Sieve of Eratosthenes."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_primes_smaller(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" return primes\n",
"\n",
"assert(get_primes_smaller(0) == [])\n",
"assert(get_primes_smaller(10) == [2, 3, 5, 7,])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we create a function which does prime factorization. It is very important that we only test primes smaller than the squre root. Otherwise the complexity becomes too big."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import math\n",
"\n",
"def get_prime_factors(number):\n",
" possible_factors = get_primes_smaller(math.ceil(math.sqrt(number)))\n",
" remainder = number\n",
" factors = []\n",
" for p in possible_factors:\n",
" while remainder % p == 0:\n",
" remainder /= p\n",
" factors.append(p)\n",
" if remainder == 1:\n",
" break\n",
" if remainder != 1:\n",
" factors.append(remainder)\n",
" return factors\n",
"\n",
"assert(get_prime_factors(7) == [7])\n",
"assert(get_prime_factors(12) == [2, 2, 3]) \n",
"assert(get_prime_factors(88) == [2, 2, 2, 11]) \n",
"assert(get_prime_factors(13195) == [5, 7, 13, 29])\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can go ahead an brute force the solution."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6857\n"
]
}
],
"source": [
"def get_largest_prime(number):\n",
" return get_prime_factors(number)[-1]\n",
"\n",
"assert(get_largest_prime(13195) == 29)\n",
"#print(get_largest_prime(600851475143))\n",
"print(6857) # computed the previously but remove it so that we can reexecute the complete kernel"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Okay, actually we can brute force, but it is really slow. A better solution is to write a prime number generator which calculates the next number on demand."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6857\n"
]
}
],
"source": [
"def is_prime(n, smaller_primes):\n",
" for s in smaller_primes:\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
"\n",
"def prime_generator_function():\n",
" primes = [2, 3, 5, 7]\n",
" for p in primes:\n",
" yield p\n",
" while True:\n",
" p += 2\n",
" if is_prime(p, primes):\n",
" primes.append(p)\n",
" yield p\n",
" \n",
"def get_prime_factors(number):\n",
" prime_generator = prime_generator_function()\n",
" remainder = number\n",
" factors = []\n",
" for p in prime_generator:\n",
" while remainder % p == 0:\n",
" remainder /= p\n",
" factors.append(p)\n",
" if remainder == 1 or p * p > number:\n",
" break\n",
" if remainder != 1:\n",
" factors.append(remainder)\n",
" return factors\n",
"\n",
"print(get_largest_prime(600851475143))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we go. Obviously much better than precalculation primes that we never need."
]
}
],
"metadata": {
"completion_date": "Tue, 19 Aug 2014, 23:35",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"prime"
]
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@ -1,180 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 4\n",
"\n",
"A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.\n",
"\n",
"Find the largest palindrome made from the product of two 3-digit numbers."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No big magic going on in this solution. We apply brute force. The only optimization we take is starting from the back so that the first palindrome should be the largest. However, we first implement a simple function to check whether an integer is a palindrome."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def is_palindrome(n):\n",
" assert(type(n) is int)\n",
" n = str(n)\n",
" a, b = 0, len(n) - 1\n",
" while a < b:\n",
" if n[a] != n[b]:\n",
" return False\n",
" a += 1\n",
" b -= 1\n",
" return True\n",
"\n",
"assert(is_palindrome(9009) is True)\n",
"assert(is_palindrome(909) is True)\n",
"assert(is_palindrome(1) is True)\n",
"assert(is_palindrome(908) is False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Get potential solutions. Generating a list comprehension which sorts the products in decreasing order is actually not that easys. This is because if we use two ranges it is not straight foward to decide which product is smaller or bigger. In the following example. 9 times 7 is still bigger than 8 times 8, but 9 times 6 is not anymore. So let's go for brute force the hard way."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(9, 9), (9, 8), (9, 7), (9, 6), (9, 5), (9, 4), (9, 3), (9, 2), (9, 1), (8, 8), (8, 7), (8, 6), (8, 5), (8, 4), (8, 3), (8, 2), (8, 1), (7, 7), (7, 6), (7, 5), (7, 4), (7, 3), (7, 2), (7, 1), (6, 6), (6, 5), (6, 4), (6, 3), (6, 2), (6, 1), (5, 5), (5, 4), (5, 3), (5, 2), (5, 1), (4, 4), (4, 3), (4, 2), (4, 1), (3, 3), (3, 2), (3, 1), (2, 2), (2, 1), (1, 1)]\n"
]
}
],
"source": [
"pairs = ((a, b) for a in range(9, 0, -1) for b in range(a, 0, -1))\n",
"print(list(pairs))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We iterate over all 3-digit pairs. Two avoid duplicates the second range starts at the current value of the first range. If the new product is greater than the old one and a palindrome we have found a new result."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2.844880788875627\n",
"906609\n"
]
}
],
"source": [
"import timeit\n",
"\n",
"def brute_force():\n",
" r = 0\n",
" for a in range(999, 99, -1):\n",
" for b in range(a, 99, -1):\n",
" c = a * b\n",
" if c > r and is_palindrome(c):\n",
" r = c\n",
" return r\n",
"\n",
"print(timeit.timeit(brute_force, number=100))\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To do some more optimization we can simply break the loops if the square of the outer loop is smaller than the current result. If we find the solution quiet early this will prevent iterating through a lot of values which cannot yield a better result."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.562125718678324\n",
"906609\n"
]
}
],
"source": [
"def brute_force():\n",
" r = 0\n",
" for a in range(999, 99, -1):\n",
" if a * a < r:\n",
" break\n",
" for b in range(a, 99, -1):\n",
" c = a * b\n",
" if c > r and is_palindrome(c):\n",
" r = c\n",
" return r\n",
"\n",
"print(timeit.timeit(brute_force, number=100))\n",
"print(brute_force())"
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 13:27",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"palindrome",
"combinations",
"brute force",
"timeit"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,135 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem\n",
"\n",
"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.\n",
"\n",
"What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"My easiest guess is to multiply all prime numbers till the number."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_primes_smaller(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" return primes"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"210\n"
]
}
],
"source": [
"from operator import mul\n",
"from functools import reduce\n",
"\n",
"def get_number_which_is_divisible_by_all_numbers_from_one_to(n):\n",
" ps= get_primes_smaller(n + 1)\n",
" return reduce(mul, ps, 1)\n",
"\n",
"print(get_number_which_is_divisible_by_all_numbers_from_one_to(10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That obviously didn't work. The reason is that the same prime can occur multiple times in the factorization of a divisor. For example $2^{3} = 8$. We can always brute force of course. We do a smart brute force and only check multiples from the product of primes because this factor must be part of the solution."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"232792560\n"
]
}
],
"source": [
"def is_divisible_by_numbers_smaller_or_equal(number, maximum_number):\n",
" for n in range(2, maximum_number + 1):\n",
" if number % n != 0:\n",
" return False\n",
" return True\n",
"\n",
"def get_number_which_is_divisible_by_all_numbers_from_one_to(n):\n",
" ps = get_primes_smaller(n + 1)\n",
" factor = reduce(mul, ps, 1)\n",
" multiples_of_factor = factor\n",
" while True:\n",
" if is_divisible_by_numbers_smaller_or_equal(multiples_of_factor, n):\n",
" return multiples_of_factor\n",
" multiples_of_factor += factor\n",
"\n",
"assert(get_number_which_is_divisible_by_all_numbers_from_one_to(10) == 2520)\n",
"print(get_number_which_is_divisible_by_all_numbers_from_one_to(20))"
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 14:32",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"reduce",
"divisible"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,96 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 6\n",
"\n",
"The sum of the squares of the first ten natural numbers is,\n",
"\n",
"$1^2 + 2^2 + ... + 10^2 = 385$\n",
"\n",
"The square of the sum of the first ten natural numbers is,\n",
"\n",
"$(1 + 2 + ... + 10)^2 = 55^2 = 3025$\n",
"\n",
"Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is $3025 385 = 2640$.\n",
"\n",
"Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, this is as straightforward as it can get."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"25164150\n"
]
}
],
"source": [
"s = sum([x for x in range(1, 101)])**2 - sum([x**2 for x in range(1, 101)])\n",
"assert(s == 25164150)\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"General solution."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def diff_between_sum_of_squares_and_square_sum(n):\n",
" return sum([x for x in range(1, n + 1)])**2 - sum([x**2 for x in range(1, n + 1)])\n",
"\n",
"assert(diff_between_sum_of_squares_and_square_sum(100) == 25164150)\n",
"assert(diff_between_sum_of_squares_and_square_sum(10) == 2640)"
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 15:13",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": []
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,94 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 7\n",
"\n",
"By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.\n",
"\n",
"What is the 10 001st prime number?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We reuse our prime functions and use a trick from [stackoverflow](https://stackoverflow.com/questions/2300756/get-the-nth-item-of-a-generator-in-python) to get the nth element."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"104743\n"
]
}
],
"source": [
"import itertools\n",
"\n",
"def is_prime(n, smaller_primes):\n",
" for s in smaller_primes:\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
"\n",
"def prime_generator_function():\n",
" primes = [2, 3, 5, 7]\n",
" for p in primes:\n",
" yield p\n",
" while True:\n",
" p += 2\n",
" if is_prime(p, primes):\n",
" primes.append(p)\n",
" yield p\n",
"\n",
"def get_nth_prime(n):\n",
" ps = prime_generator_function()\n",
" return next(itertools.islice(ps, n - 1, n))\n",
"\n",
"assert(get_nth_prime(6) == 13)\n",
"print(get_nth_prime(10001))"
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 15:40",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"prime",
"nth prime",
"nth",
"generator"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,144 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 8\n",
"\n",
"The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.\n",
"\n",
"~~~\n",
"73167176531330624919225119674426574742355349194934\n",
"96983520312774506326239578318016984801869478851843\n",
"85861560789112949495459501737958331952853208805511\n",
"12540698747158523863050715693290963295227443043557\n",
"66896648950445244523161731856403098711121722383113\n",
"62229893423380308135336276614282806444486645238749\n",
"30358907296290491560440772390713810515859307960866\n",
"70172427121883998797908792274921901699720888093776\n",
"65727333001053367881220235421809751254540594752243\n",
"52584907711670556013604839586446706324415722155397\n",
"53697817977846174064955149290862569321978468622482\n",
"83972241375657056057490261407972968652414535100474\n",
"82166370484403199890008895243450658541227588666881\n",
"16427171479924442928230863465674813919123162824586\n",
"17866458359124566529476545682848912883142607690042\n",
"24219022671055626321111109370544217506941658960408\n",
"07198403850962455444362981230987879927244284909188\n",
"84580156166097919133875499200524063689912560717606\n",
"05886116467109405077541002256983155200055935729725\n",
"71636269561882670428252483600823257530420752963450\n",
"~~~\n",
"\n",
"Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We need the number as a list of integers first."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def remove_newlines(s):\n",
" import re\n",
" return re.sub(r'\\n', '', s)\n",
"\n",
"digits_string = \"\"\"73167176531330624919225119674426574742355349194934\n",
"96983520312774506326239578318016984801869478851843\n",
"85861560789112949495459501737958331952853208805511\n",
"12540698747158523863050715693290963295227443043557\n",
"66896648950445244523161731856403098711121722383113\n",
"62229893423380308135336276614282806444486645238749\n",
"30358907296290491560440772390713810515859307960866\n",
"70172427121883998797908792274921901699720888093776\n",
"65727333001053367881220235421809751254540594752243\n",
"52584907711670556013604839586446706324415722155397\n",
"53697817977846174064955149290862569321978468622482\n",
"83972241375657056057490261407972968652414535100474\n",
"82166370484403199890008895243450658541227588666881\n",
"16427171479924442928230863465674813919123162824586\n",
"17866458359124566529476545682848912883142607690042\n",
"24219022671055626321111109370544217506941658960408\n",
"07198403850962455444362981230987879927244284909188\n",
"84580156166097919133875499200524063689912560717606\n",
"05886116467109405077541002256983155200055935729725\n",
"71636269561882670428252483600823257530420752963450\"\"\"\n",
"\n",
"digits = [int(d) for d in remove_newlines(digits_string)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" Then we can use slicing to do a brute force."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"23514624000\n"
]
}
],
"source": [
"def product(xs):\n",
" from operator import mul\n",
" from functools import reduce\n",
" return reduce(mul, xs, 1)\n",
"\n",
"def get_largest_product_of_n_digits(digits, n):\n",
" return max((product(digits[i:i + n]) for i in range(len(digits))))\n",
"\n",
"assert(get_largest_product_of_n_digits(digits, 4) == 5832)\n",
"assert(get_largest_product_of_n_digits(digits, 13) == 23514624000)\n",
"print(get_largest_product_of_n_digits(digits, 13))"
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 16:03",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"product",
"reduce",
"slice"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,165 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 9\n",
"\n",
"A Pythagorean triplet is a set of three natural numbers, $a < b < c$, for which,\n",
"\n",
"$a^2 + b^2 = c^2$\n",
"\n",
"For example, $3^2 + 4^2 = 9 + 16 = 25 = 5^2$.\n",
"\n",
"There exists exactly one Pythagorean triplet for which $a + b + c = 1000$.\n",
"Find the product $abc$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start bruteforcing even though it feels like there may be a smart solution."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"66.96907186399949\n",
"31875000\n"
]
}
],
"source": [
"import timeit\n",
"\n",
"def brute_force():\n",
" for a in range(1, 251):\n",
" for b in range(a + 1, 501):\n",
" for c in range(b + 1, 1001):\n",
" if a + b + c == 1000 and a * a + b * b == c * c:\n",
" return a * b * c\n",
"\n",
"print(timeit.timeit(brute_force, number=10))\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's do some optimization by cancelling the loops when we exceed the boundaries. Actually, I have also realized that choosing 251 and 501 is a little bit arbitrary. For example if a, b, c where something like $332, 333, 335$ that could be a solution and the first range was too low. Then again, we would have realized that as soon as we get back None, so it is okay."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"64.4656584559998\n",
"31875000\n"
]
}
],
"source": [
"def brute_force():\n",
" for a in range(1, 251):\n",
" for b in range(a + 1, 501):\n",
" if a + b > 600:\n",
" break\n",
" for c in range(b + 1, 1001):\n",
" if a + b + c == 1000 and a * a + b * b == c * c:\n",
" return a * b * c\n",
" \n",
"print(timeit.timeit(brute_force, number=10))\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Big time save. Kappa. Okay, I am stupid. If I have a and b I can calculate c and check if it is a solution."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.22822808900036762\n",
"31875000\n"
]
}
],
"source": [
"def smart_brute_force():\n",
" for a in range(1, 251):\n",
" for b in range(a + 1, 501):\n",
" c = 1000 - a - b\n",
" if a * a + b * b == c * c:\n",
" return a * b * c\n",
" \n",
"print(timeit.timeit(smart_brute_force, number=10))\n",
"print(smart_brute_force()) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 17:06",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"brute force",
"pythagorean",
"triplet"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,182 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 10\n",
"\n",
"The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.\n",
"\n",
"Find the sum of all the primes below two million."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, reuse prime generator from 7 and go."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"61.8695481220002\n",
"142913828922\n"
]
}
],
"source": [
"import timeit\n",
"\n",
"def is_prime(n, smaller_primes):\n",
" for s in smaller_primes:\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
"\n",
"def prime_generator_function():\n",
" primes = [2, 3, 5, 7]\n",
" for p in primes:\n",
" yield p\n",
" while True:\n",
" p += 2\n",
" if is_prime(p, primes):\n",
" primes.append(p)\n",
" yield p\n",
" \n",
"def brute_force(): \n",
" ps = prime_generator_function()\n",
" s = 0\n",
" p = next(ps)\n",
" while p < 2000000:\n",
" s += p\n",
" p = next(ps)\n",
" return s\n",
" \n",
"print(timeit.timeit(brute_force, number=10))\n",
"assert(brute_force() == 142913828922)\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, here it may actually be way smarter to use a sieve. We implent it because the old one was shitty. Okay, I am actually interested in the time difference. So we use the old one first and then implement the optimization."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_primes_smaller(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" return primes\n",
"\n",
"def brute_force():\n",
" return sum(get_primes_smaller(2000000))\n",
"\n",
"#print(timeit.timeit(brute_force, number=1))\n",
"#print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This did not even terminate. We optimize the sieve by stopping when $p^2 > number$."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"74.5315607270004\n",
"142913828922\n"
]
}
],
"source": [
"def sieve_of_eratosthenes(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > number:\n",
" break\n",
" return primes + prospects\n",
"\n",
"def brute_force():\n",
" return sum(sieve_of_eratosthenes(2000000))\n",
"\n",
"assert(sieve_of_eratosthenes(10) == [2, 3, 5, 7,])\n",
"print(timeit.timeit(brute_force, number=10))\n",
"assert(brute_force() == 142913828922)\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, I honestly did not expect this to be slower than our generator. Gotta keep that in mind for future prime related problems."
]
}
],
"metadata": {
"completion_date": "Wed, 20 Aug 2014, 20:28",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"primes",
"brute force",
"timeit"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,187 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 11\n",
"\n",
"In the 20×20 grid below, four numbers along a diagonal line have been marked in red.\n",
"\n",
"~~~\n",
"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\n",
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\n",
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\n",
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\n",
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\n",
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\n",
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\n",
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\n",
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\n",
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\n",
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\n",
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\n",
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\n",
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\n",
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\n",
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\n",
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\n",
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\n",
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\n",
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48\n",
"~~~\n",
"\n",
"The product of these numbers is $26 × 63 × 78 × 14 = 1788696$.\n",
"\n",
"What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start by parsing the array into three lists of lists (horizontal, diagonal, vertical).\n",
"\n",
"97, 17, 79, 11, 89, 44, 38, 94, 78, 0, 62, 54, 58, 4, 27, 53, 36, 1, 1, 1]"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"s = \"\"\"\n",
"08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\n",
"49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\n",
"81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\n",
"52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\n",
"22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\n",
"24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\n",
"32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\n",
"67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\n",
"24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\n",
"21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\n",
"78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\n",
"16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\n",
"86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\n",
"19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\n",
"04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\n",
"88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\n",
"04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\n",
"20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\n",
"20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\n",
"01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48\n",
"\"\"\"\n",
"\n",
"def get_index(xs, index, default):\n",
" if index < 0:\n",
" return default\n",
" try:\n",
" return xs[index]\n",
" except IndexError:\n",
" return default\n",
"\n",
"hss = [list(map(int, h.split())) for h in s.split('\\n') if h]\n",
"vss = [list(vs) for vs in zip(*hss)]\n",
"# diagonal from top left to bottom right\n",
"dss = [[get_index(hs, -19 + i + j, 1) for j, hs in enumerate(hss)] for i in range(39)]\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I really love the way we retrieve the vertical list. (We need the ugly conversion to list because otherwise we cannot concatenate them.) It is at the limit of my mental capabilities to understand why this works. But actually it is quite straight forward. If we provide two lists, zip creates a two-tuple for each field in the lists. If we provide n lists, zip creates a n-tuple for each field in the lists. Easy.\n",
"\n",
"Now we create big list of lists and search each one for the greates four product and then get the maximum. Straight forward. We borrow the find product function from problem 8 because I like it."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"xss = hss + vss + dss\n",
"\n",
"def product(xs):\n",
" from operator import mul\n",
" from functools import reduce\n",
" return reduce(mul, xs, 1)\n",
"\n",
"def get_largest_product_of_n_digits(xs, n):\n",
" return max([product(xs[i:i + n]) for i in range(len(xs))])\n",
"\n",
"s = max([get_largest_product_of_n_digits(xs, 4) for xs in xss])\n",
"assert(s != 70600674)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, I am actually really dumb. I forgot about the other diagonal. I think I have made the same mistake back when I solved this for the first time. So let's get the missing dss and get the solution."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"70600674\n"
]
}
],
"source": [
"# diagonal from bottom left to top right\n",
"hss.reverse()\n",
"dss = [[get_index(hs, -19 + i + j, 1) for j, hs in enumerate(hss)] for i in range(39)]\n",
"\n",
"s = max([get_largest_product_of_n_digits(ds, 4) for ds in dss])\n",
"assert(s == 70600674)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 07:39",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"brute force",
"product",
"matrix",
"tricky",
"diagonal"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,252 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 12\n",
"\n",
"The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be $1 + 2 + 3 + 4 + 5 + 6 + 7 = 28$. The first ten terms would be:\n",
"\n",
"$1, 3, 6, 10, 15, 21, 28, 36, 45, 55, \\dots$\n",
"\n",
"Let us list the factors of the first seven triangle numbers:\n",
"\n",
"~~~\n",
" 1: 1\n",
" 3: 1,3\n",
" 6: 1,2,3,6\n",
"10: 1,2,5,10\n",
"15: 1,3,5,15\n",
"21: 1,3,7,21\n",
"28: 1,2,4,7,14,28\n",
"~~~\n",
"\n",
"We can see that 28 is the first triangle number to have over five divisors.\n",
"\n",
"What is the value of the first triangle number to have over five hundred divisors?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's try brute forcing."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_divisors(n):\n",
" return [i for i in range(1, int(n/2) + 1) if n % i == 0] + [n]\n",
"\n",
"assert(get_divisors(28) == [1,2,4,7,14,28])\n",
"\n",
"def triangle_number_generator_function():\n",
" c = 0\n",
" for i in range(1, 100000000000):\n",
" c += i\n",
" yield c\n",
"\n",
"#ts = triangle_number_generator_function()\n",
"#for t in ts:\n",
"# if len(get_divisors(t)) > 500:\n",
"# print(t)\n",
"# break\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That failed miserably. We have to come up with something more efficient. I looked at my old Haskell solution which looks like this:\n",
"\n",
"~~~\n",
"divisor_count' x = product . map (succ . length) . group $ prim_factors x\n",
"~~~\n",
"\n",
"Add first I did not understand what it does at all. But the algorithm is as follows:\n",
"\n",
"~~~\n",
"# get prime factors, for example for 28\n",
"2 * 2 * 7\n",
"# group the primes\n",
"[[2, 2], [7]]\n",
"# get the length of each group and increment it by one\n",
"[3, 2]\n",
"# get the product of all values\n",
"6\n",
"~~~\n",
"\n",
"Honestly, I have no idea why this gives as the number of divisors. I will implement the solution and then try to come up with an explanation."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_prime(n, smaller_primes):\n",
" for s in smaller_primes:\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
"\n",
"def prime_generator_function():\n",
" primes = [2, 3, 5, 7]\n",
" for p in primes:\n",
" yield p\n",
" while True:\n",
" p += 2\n",
" if is_prime(p, primes):\n",
" primes.append(p)\n",
" yield p\n",
" \n",
"def get_prime_factors(number):\n",
" prime_generator = prime_generator_function()\n",
" remainder = number\n",
" factors = []\n",
" for p in prime_generator:\n",
" while remainder % p == 0:\n",
" remainder /= p\n",
" factors.append(p)\n",
" if remainder == 1 or p * p > number:\n",
" break\n",
" if remainder != 1:\n",
" factors.append(remainder)\n",
" return factors"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This are the prime numbers related functions we already now. Now we implement a group function, the product function we already know, and based on that the algorithm to get the number of divisors mentioned above."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def group(xs):\n",
" from functools import reduce\n",
" def f(xss, x):\n",
" if xss and x in xss[-1]:\n",
" xss[-1].append(x)\n",
" else:\n",
" xss.append([x])\n",
" return xss\n",
" return reduce(f, xs, [])\n",
"\n",
"def product(xs):\n",
" from functools import reduce\n",
" from operator import mul\n",
" return reduce(mul, xs, 1)\n",
"\n",
"assert(group([1, 1, 3, 2, 2]) == [[1, 1], [3], [2, 2]])\n",
"\n",
"def get_number_of_divisors(n):\n",
" # get prime factors, for example for 28\n",
" ps = get_prime_factors(n)\n",
" # group the primes\n",
" ps = group(ps)\n",
" # get the length of each group and increment it by one\n",
" ps = map(lambda x: len(x) + 1, ps)\n",
" # get the product of all values\n",
" return product(ps)\n",
" \n",
"assert(get_number_of_divisors(28) == 6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we are ready to do another brute force attempt."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"76576500\n"
]
}
],
"source": [
"ts = triangle_number_generator_function()\n",
"for t in ts:\n",
" if get_number_of_divisors(t) > 500:\n",
" print(t)\n",
" break"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now the only question is why this crazy algorithm works. Okay, I got it with the help of [this](https://www.math.upenn.edu/~deturck/m170/wk2/numdivisors.html) page. The problem is actually an instance of the multiplication principle for counting things. Each prime can be used to calculate (n + 1) other divisors. The incrementation by one is required because we can also choose to not use a certain prime. Of course, to get the potential combinations we have to get the product of the potential divisors for all primes. The web page explains it better. The only question is whether I came up with this algorithm myself back then."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 17:07",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"triangular",
"number",
"divisors",
"factorization",
"prime",
"group"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,273 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 13\n",
"\n",
"Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.\n",
"\n",
"~~~\n",
"37107287533902102798797998220837590246510135740250\n",
"46376937677490009712648124896970078050417018260538\n",
"74324986199524741059474233309513058123726617309629\n",
"91942213363574161572522430563301811072406154908250\n",
"23067588207539346171171980310421047513778063246676\n",
"89261670696623633820136378418383684178734361726757\n",
"28112879812849979408065481931592621691275889832738\n",
"44274228917432520321923589422876796487670272189318\n",
"47451445736001306439091167216856844588711603153276\n",
"70386486105843025439939619828917593665686757934951\n",
"62176457141856560629502157223196586755079324193331\n",
"64906352462741904929101432445813822663347944758178\n",
"92575867718337217661963751590579239728245598838407\n",
"58203565325359399008402633568948830189458628227828\n",
"80181199384826282014278194139940567587151170094390\n",
"35398664372827112653829987240784473053190104293586\n",
"86515506006295864861532075273371959191420517255829\n",
"71693888707715466499115593487603532921714970056938\n",
"54370070576826684624621495650076471787294438377604\n",
"53282654108756828443191190634694037855217779295145\n",
"36123272525000296071075082563815656710885258350721\n",
"45876576172410976447339110607218265236877223636045\n",
"17423706905851860660448207621209813287860733969412\n",
"81142660418086830619328460811191061556940512689692\n",
"51934325451728388641918047049293215058642563049483\n",
"62467221648435076201727918039944693004732956340691\n",
"15732444386908125794514089057706229429197107928209\n",
"55037687525678773091862540744969844508330393682126\n",
"18336384825330154686196124348767681297534375946515\n",
"80386287592878490201521685554828717201219257766954\n",
"78182833757993103614740356856449095527097864797581\n",
"16726320100436897842553539920931837441497806860984\n",
"48403098129077791799088218795327364475675590848030\n",
"87086987551392711854517078544161852424320693150332\n",
"59959406895756536782107074926966537676326235447210\n",
"69793950679652694742597709739166693763042633987085\n",
"41052684708299085211399427365734116182760315001271\n",
"65378607361501080857009149939512557028198746004375\n",
"35829035317434717326932123578154982629742552737307\n",
"94953759765105305946966067683156574377167401875275\n",
"88902802571733229619176668713819931811048770190271\n",
"25267680276078003013678680992525463401061632866526\n",
"36270218540497705585629946580636237993140746255962\n",
"24074486908231174977792365466257246923322810917141\n",
"91430288197103288597806669760892938638285025333403\n",
"34413065578016127815921815005561868836468420090470\n",
"23053081172816430487623791969842487255036638784583\n",
"11487696932154902810424020138335124462181441773470\n",
"63783299490636259666498587618221225225512486764533\n",
"67720186971698544312419572409913959008952310058822\n",
"95548255300263520781532296796249481641953868218774\n",
"76085327132285723110424803456124867697064507995236\n",
"37774242535411291684276865538926205024910326572967\n",
"23701913275725675285653248258265463092207058596522\n",
"29798860272258331913126375147341994889534765745501\n",
"18495701454879288984856827726077713721403798879715\n",
"38298203783031473527721580348144513491373226651381\n",
"34829543829199918180278916522431027392251122869539\n",
"40957953066405232632538044100059654939159879593635\n",
"29746152185502371307642255121183693803580388584903\n",
"41698116222072977186158236678424689157993532961922\n",
"62467957194401269043877107275048102390895523597457\n",
"23189706772547915061505504953922979530901129967519\n",
"86188088225875314529584099251203829009407770775672\n",
"11306739708304724483816533873502340845647058077308\n",
"82959174767140363198008187129011875491310547126581\n",
"97623331044818386269515456334926366572897563400500\n",
"42846280183517070527831839425882145521227251250327\n",
"55121603546981200581762165212827652751691296897789\n",
"32238195734329339946437501907836945765883352399886\n",
"75506164965184775180738168837861091527357929701337\n",
"62177842752192623401942399639168044983993173312731\n",
"32924185707147349566916674687634660915035914677504\n",
"99518671430235219628894890102423325116913619626622\n",
"73267460800591547471830798392868535206946944540724\n",
"76841822524674417161514036427982273348055556214818\n",
"97142617910342598647204516893989422179826088076852\n",
"87783646182799346313767754307809363333018982642090\n",
"10848802521674670883215120185883543223812876952786\n",
"71329612474782464538636993009049310363619763878039\n",
"62184073572399794223406235393808339651327408011116\n",
"66627891981488087797941876876144230030984490851411\n",
"60661826293682836764744779239180335110989069790714\n",
"85786944089552990653640447425576083659976645795096\n",
"66024396409905389607120198219976047599490197230297\n",
"64913982680032973156037120041377903785566085089252\n",
"16730939319872750275468906903707539413042652315011\n",
"94809377245048795150954100921645863754710598436791\n",
"78639167021187492431995700641917969777599028300699\n",
"15368713711936614952811305876380278410754449733078\n",
"40789923115535562561142322423255033685442488917353\n",
"44889911501440648020369068063960672322193204149535\n",
"41503128880339536053299340368006977710650566631954\n",
"81234880673210146739058568557934581403627822703280\n",
"82616570773948327592232845941706525094512325230608\n",
"22918802058777319719839450180888072429661980811197\n",
"77158542502016545090413245809786882778948721859617\n",
"72107838435069186155435662884062257473692284509516\n",
"20849603980134001723930671666823555245252804609722\n",
"53503534226472524250874054075591789781264330331690\n",
"~~~"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Straight forward. No big deal."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5537376230\n"
]
}
],
"source": [
"numbers_string = \"\"\"\n",
"37107287533902102798797998220837590246510135740250\n",
"46376937677490009712648124896970078050417018260538\n",
"74324986199524741059474233309513058123726617309629\n",
"91942213363574161572522430563301811072406154908250\n",
"23067588207539346171171980310421047513778063246676\n",
"89261670696623633820136378418383684178734361726757\n",
"28112879812849979408065481931592621691275889832738\n",
"44274228917432520321923589422876796487670272189318\n",
"47451445736001306439091167216856844588711603153276\n",
"70386486105843025439939619828917593665686757934951\n",
"62176457141856560629502157223196586755079324193331\n",
"64906352462741904929101432445813822663347944758178\n",
"92575867718337217661963751590579239728245598838407\n",
"58203565325359399008402633568948830189458628227828\n",
"80181199384826282014278194139940567587151170094390\n",
"35398664372827112653829987240784473053190104293586\n",
"86515506006295864861532075273371959191420517255829\n",
"71693888707715466499115593487603532921714970056938\n",
"54370070576826684624621495650076471787294438377604\n",
"53282654108756828443191190634694037855217779295145\n",
"36123272525000296071075082563815656710885258350721\n",
"45876576172410976447339110607218265236877223636045\n",
"17423706905851860660448207621209813287860733969412\n",
"81142660418086830619328460811191061556940512689692\n",
"51934325451728388641918047049293215058642563049483\n",
"62467221648435076201727918039944693004732956340691\n",
"15732444386908125794514089057706229429197107928209\n",
"55037687525678773091862540744969844508330393682126\n",
"18336384825330154686196124348767681297534375946515\n",
"80386287592878490201521685554828717201219257766954\n",
"78182833757993103614740356856449095527097864797581\n",
"16726320100436897842553539920931837441497806860984\n",
"48403098129077791799088218795327364475675590848030\n",
"87086987551392711854517078544161852424320693150332\n",
"59959406895756536782107074926966537676326235447210\n",
"69793950679652694742597709739166693763042633987085\n",
"41052684708299085211399427365734116182760315001271\n",
"65378607361501080857009149939512557028198746004375\n",
"35829035317434717326932123578154982629742552737307\n",
"94953759765105305946966067683156574377167401875275\n",
"88902802571733229619176668713819931811048770190271\n",
"25267680276078003013678680992525463401061632866526\n",
"36270218540497705585629946580636237993140746255962\n",
"24074486908231174977792365466257246923322810917141\n",
"91430288197103288597806669760892938638285025333403\n",
"34413065578016127815921815005561868836468420090470\n",
"23053081172816430487623791969842487255036638784583\n",
"11487696932154902810424020138335124462181441773470\n",
"63783299490636259666498587618221225225512486764533\n",
"67720186971698544312419572409913959008952310058822\n",
"95548255300263520781532296796249481641953868218774\n",
"76085327132285723110424803456124867697064507995236\n",
"37774242535411291684276865538926205024910326572967\n",
"23701913275725675285653248258265463092207058596522\n",
"29798860272258331913126375147341994889534765745501\n",
"18495701454879288984856827726077713721403798879715\n",
"38298203783031473527721580348144513491373226651381\n",
"34829543829199918180278916522431027392251122869539\n",
"40957953066405232632538044100059654939159879593635\n",
"29746152185502371307642255121183693803580388584903\n",
"41698116222072977186158236678424689157993532961922\n",
"62467957194401269043877107275048102390895523597457\n",
"23189706772547915061505504953922979530901129967519\n",
"86188088225875314529584099251203829009407770775672\n",
"11306739708304724483816533873502340845647058077308\n",
"82959174767140363198008187129011875491310547126581\n",
"97623331044818386269515456334926366572897563400500\n",
"42846280183517070527831839425882145521227251250327\n",
"55121603546981200581762165212827652751691296897789\n",
"32238195734329339946437501907836945765883352399886\n",
"75506164965184775180738168837861091527357929701337\n",
"62177842752192623401942399639168044983993173312731\n",
"32924185707147349566916674687634660915035914677504\n",
"99518671430235219628894890102423325116913619626622\n",
"73267460800591547471830798392868535206946944540724\n",
"76841822524674417161514036427982273348055556214818\n",
"97142617910342598647204516893989422179826088076852\n",
"87783646182799346313767754307809363333018982642090\n",
"10848802521674670883215120185883543223812876952786\n",
"71329612474782464538636993009049310363619763878039\n",
"62184073572399794223406235393808339651327408011116\n",
"66627891981488087797941876876144230030984490851411\n",
"60661826293682836764744779239180335110989069790714\n",
"85786944089552990653640447425576083659976645795096\n",
"66024396409905389607120198219976047599490197230297\n",
"64913982680032973156037120041377903785566085089252\n",
"16730939319872750275468906903707539413042652315011\n",
"94809377245048795150954100921645863754710598436791\n",
"78639167021187492431995700641917969777599028300699\n",
"15368713711936614952811305876380278410754449733078\n",
"40789923115535562561142322423255033685442488917353\n",
"44889911501440648020369068063960672322193204149535\n",
"41503128880339536053299340368006977710650566631954\n",
"81234880673210146739058568557934581403627822703280\n",
"82616570773948327592232845941706525094512325230608\n",
"22918802058777319719839450180888072429661980811197\n",
"77158542502016545090413245809786882778948721859617\n",
"72107838435069186155435662884062257473692284509516\n",
"20849603980134001723930671666823555245252804609722\n",
"53503534226472524250874054075591789781264330331690\n",
"\"\"\"\n",
"\n",
"numbers = [int(n) for n in numbers_string.split('\\n') if n]\n",
"numbers_sum = sum(numbers)\n",
"first_ten_digits = str(numbers_sum)[:10]\n",
"assert(first_ten_digits == \"5537376230\")\n",
"print(first_ten_digits)\n"
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 19:03",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"brute force",
"sum"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,162 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 14\n",
"\n",
"The following iterative sequence is defined for the set of positive integers:\n",
"\n",
"n → n/2 (n is even)\n",
"n → 3n + 1 (n is odd)\n",
"\n",
"Using the rule above and starting with 13, we generate the following sequence:\n",
"\n",
"$13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1$\n",
"\n",
"It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.\n",
"\n",
"Which starting number, under one million, produces the longest chain?\n",
"\n",
"NOTE: Once the chain starts the terms are allowed to go above one million."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I would go for a recursive function with a cache here. This should give us good performance with acceptable memory footprint."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from functools import lru_cache\n",
"from collections import deque\n",
"\n",
"@lru_cache(maxsize=11000000)\n",
"def get_collatz_sequence(n):\n",
" if n == 1:\n",
" return deque([1])\n",
" ds = get_collatz_sequence(n // 2) if n % 2 == 0 else get_collatz_sequence(3 * n + 1)\n",
" ds.appendleft(n)\n",
" return ds\n",
"\n",
"assert(list(get_collatz_sequence(13)) == [13, 40, 20, 10, 5, 16, 8, 4, 2, 1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Isn't this a beautiful solution? We need a deque to appendleft. Of course, we could also use a regular list and reverse the result, but it is nicer to get the correct solution out right away. Now we simply force the solution."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Okay, we need a loop.\n"
]
}
],
"source": [
"try:\n",
" s = max([(len(get_collatz_sequence(i)), i) for i in range(1000000)])\n",
" print(s)\n",
" assert(s == 837799)\n",
"except RecursionError:\n",
" print(\"Okay, we need a loop.\")\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"11.4885111964837\n",
"837799\n"
]
}
],
"source": [
"cache = {}\n",
"\n",
"def get_collatz_sequence(n):\n",
" global cache\n",
" orig_n = n\n",
" cs = []\n",
" while n != 1:\n",
" if n in cache:\n",
" cs = cs + cache[n]\n",
" cache[orig_n] = cs\n",
" return cs\n",
" cs.append(n)\n",
" n = n // 2 if n % 2 == 0 else 3 * n + 1\n",
" cs.append(n)\n",
" for i in range(len(cs)):\n",
" cache[cs[i]] = cs[i:]\n",
" return cs\n",
"\n",
"assert(list(get_collatz_sequence(13)) == [13, 40, 20, 10, 5, 16, 8, 4, 2, 1])\n",
"\n",
"def brute_force():\n",
" return max([(len(get_collatz_sequence(i)), i) for i in range(1, 1000000)])[1]\n",
"\n",
"s = brute_force()\n",
"assert(s == 837799)\n",
"\n",
"import timeit\n",
"print(timeit.timeit(brute_force, number=10))\n",
"print(brute_force())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we go. Takes some time. We could optimize by caching only the length and not the complete list."
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 19:45",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"tags": [
"collatz",
"cache",
"deque"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,99 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 15\n",
"\n",
"Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner.\n",
"\n",
"![problem picture](https://projecteuler.net/project/images/p015.gif)\n",
"\n",
"\n",
"How many such routes are there through a 20×20 grid?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We should be able to get this with some thinking. Every move for a $nxn$ grid has to contain n downward and n rightward moves. So in total there are 2n moves. Now we only have to get all permutations available with 2n moves. Normally, we would calculate the factorial, but this only works if all symbols are different. In this case we always only have two symbols for the 2n moves.\n",
"For each solution there exist a certain number of ways we can create this solution. Let's assume we have two right arrows called (1, 2) and two down arrows called (3, 4). We now have the following options to generate the solution in the upper left corner.\n",
"\n",
"~~~\n",
"1 2 3 4\n",
"1 2 4 3\n",
"2 1 3 4\n",
"2 1 4 2\n",
"~~~\n",
"\n",
"So this means if we calculate the number of ways using the factorial $(2\\times2)! = 4! = 24$, four of the solutions are equal which gives us $\\frac{24}{4} = 6$. The way to calculate the four should be $2! \\times 2! = 4$, so our formula is $\\frac{(2\\times n)!}{n! \\times n!}$. So let's try that."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"137846528820\n"
]
}
],
"source": [
"def get_number_of_routes(n):\n",
" from math import factorial\n",
" return factorial(2 * n) // (factorial(n) * factorial(n))\n",
"\n",
"assert(get_number_of_routes(2) == 6)\n",
"assert(get_number_of_routes(20) == 137846528820)\n",
"print(get_number_of_routes(20))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Would actually be interesting to see how this formular changes if we add another dimension. The number of moves would change to $3n$ obviously. And I think the number of permutations changes to remove changes to $n! \\times n! \\times n! = (n!)^3$.\n",
"\n",
"So the final formula is\n",
"\n",
"$n_{routes} = \\frac{(d \\times n)!}{(n!)^d}$\n",
"\n",
"where d is the number of dimensions and n is the size of the grid."
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 20:05",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"factorial",
"grid"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,142 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 16\n",
"\n",
"$2^{15}$ = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.\n",
"\n",
"What is the sum of the digits of the number $2^{1000}$?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Seriously? Okay, probably more difficult in C."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1366\n"
]
}
],
"source": [
"s = sum(map(int, str(2**1000)))\n",
"assert(s == 1366)\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, let's do it without big ints."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def double_number_string(number_string):\n",
" number_string = number_string[::-1] # reverse\n",
" result = []\n",
" carriage = 0\n",
" for c in number_string:\n",
" s = carriage + int(c) + int(c)\n",
" carriage = s // 10\n",
" next_digit = s % 10\n",
" result.append(str(next_digit))\n",
" if carriage > 0:\n",
" result.append(str(carriage))\n",
" result = \"\".join(result)[::-1]\n",
" return result\n",
"\n",
"assert(double_number_string(\"132\") == \"264\")\n",
"assert(double_number_string(\"965\") == \"1930\")"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1366\n"
]
}
],
"source": [
"def powers_of_two(n):\n",
" \"\"\" Retuns nth power of two as a string. \"\"\"\n",
" assert(n >= 0)\n",
" if n == 0:\n",
" return \"1\"\n",
" s = \"2\"\n",
" for _ in range(n - 1):\n",
" s = double_number_string(s)\n",
" return s\n",
"\n",
"assert(powers_of_two(3) == \"8\")\n",
"assert(powers_of_two(10) == \"1024\")\n",
"\n",
"number_string = powers_of_two(1000)\n",
"print(sum(map(int, number_string)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we go. The conversion to integer and the sum would be easy in C."
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 20:49",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"c",
"manual"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,152 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 17\n",
"\n",
"If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.\n",
"\n",
"If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?\n",
"\n",
"\n",
"NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of \"and\" when writing out numbers is in compliance with British usage."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I can see us doing a semi-automated approach here or we write a nice function. We probably write a nice function because we are geeks."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def single_digit_integer_to_spoken_language(n):\n",
" if n == 0:\n",
" return \"\"\n",
" assert(n > 0 and n < 10)\n",
" return {1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five',\n",
" 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine'}[n]\n",
"\n",
"def double_digit_integer_to_spoken_language(n):\n",
" assert(n > 9 and n < 100)\n",
" try:\n",
" return {\n",
" 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', \n",
" 14: 'fourteen', 15: 'fifteen', 16: 'sixteen',\n",
" 17: 'seventeen', 18: 'eighteen', 19: 'nineteen'}[n]\n",
" except KeyError:\n",
" pass\n",
" a, b = str(n)\n",
" a = {2: 'twenty', 3: 'thirty', 4: 'forty', 5: 'fifty',\n",
" 6: 'sixty', 7: 'seventy', 8: 'eighty', 9: 'ninety'}[int(a)]\n",
" b = integer_to_spoken_language(int(b))\n",
" return a + '-' + b\n",
"\n",
"def triple_digit_integer_to_spoken_language(n):\n",
" a, b = str(n)[0], str(n)[1:]\n",
" a = single_digit_integer_to_spoken_language(int(a))\n",
" b = integer_to_spoken_language(int(b))\n",
" if not b:\n",
" return a + \" hundred\"\n",
" return a + \" hundred and \" + b\n",
"\n",
"def four_digit_integer_to_spoken_language(n):\n",
" a, b = str(n)[0], str(n)[1:]\n",
" a = single_digit_integer_to_spoken_language(int(a))\n",
" b = integer_to_spoken_language(int(b)) \n",
" return a + \" thousand \" + b\n",
"\n",
"def integer_to_spoken_language(n):\n",
" l = len(str(n))\n",
" if l == 1:\n",
" return single_digit_integer_to_spoken_language(n)\n",
" elif l == 2:\n",
" return double_digit_integer_to_spoken_language(n)\n",
" elif l == 3:\n",
" return triple_digit_integer_to_spoken_language(n)\n",
" elif l == 4:\n",
" return four_digit_integer_to_spoken_language(n)\n",
" else:\n",
" raise Exception(\"Length not supported.\")\n",
"\n",
"assert(integer_to_spoken_language(5) == 'five')\n",
"assert(integer_to_spoken_language(19) == 'nineteen')\n",
"assert(integer_to_spoken_language(21) == 'twenty-one')\n",
"assert(integer_to_spoken_language(210) == 'two hundred and ten')\n",
"assert(integer_to_spoken_language(3000) == 'three thousand ')\n",
"assert(integer_to_spoken_language(8333) == 'eight thousand three hundred and thirty-three')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, I won't win a code golf contest but at least we can get the solution now."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"21124\n"
]
}
],
"source": [
"l = len(\"\".join([integer_to_spoken_language(i) for i in range(1, 1001)]).replace(\" \", \"\").replace(\"-\", \"\"))\n",
"assert(l == 21124)\n",
"print(l)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Made the classical fourty/forty error I have already done four years ago. Some things don't change. Also I still do not really like this problem. The Haskell solution is actually way easier to read this time."
]
}
],
"metadata": {
"completion_date": "Sun, 31 Aug 2014, 21:20",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"count",
"numbers",
"tricky"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,189 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 18\n",
"\n",
"By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.\n",
"\n",
"~~~\n",
" 3\n",
" 7 4\n",
" 2 4 6\n",
" 8 5 9 3\n",
"~~~\n",
"\n",
"That is, 3 + 7 + 4 + 9 = 23.\n",
"\n",
"Find the maximum total from top to bottom of the triangle below:\n",
"\n",
"~~~\n",
"75\n",
"95 64\n",
"17 47 82\n",
"18 35 87 10\n",
"20 04 82 47 65\n",
"19 01 23 75 03 34\n",
"88 02 77 73 07 63 67\n",
"99 65 04 28 06 16 70 92\n",
"41 41 26 56 83 40 80 70 33\n",
"41 48 72 33 47 32 37 16 94 29\n",
"53 71 44 65 25 43 91 52 97 51 14\n",
"70 11 33 28 77 73 17 78 39 68 17 57\n",
"91 71 52 38 17 14 91 43 58 50 27 29 48\n",
"63 66 04 68 89 53 67 30 73 16 69 87 40 31\n",
"04 62 98 27 23 09 70 98 73 93 38 53 60 04 23\n",
"~~~\n",
"\n",
"NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route. However, [Problem 67](https://projecteuler.net/problem=67), is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is incredibly simple we simply from bottom to top choosing the higher value for each mini-tree.\n",
"\n",
"For example,\n",
"\n",
"~~~\n",
" 95 64\n",
"17 47 82\n",
"~~~\n",
"\n",
"will become:\n",
"\n",
"~~~\n",
" 142 146\n",
"~~~"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"t = \"\"\"\n",
"75\n",
"95 64\n",
"17 47 82\n",
"18 35 87 10\n",
"20 04 82 47 65\n",
"19 01 23 75 03 34\n",
"88 02 77 73 07 63 67\n",
"99 65 04 28 06 16 70 92\n",
"41 41 26 56 83 40 80 70 33\n",
"41 48 72 33 47 32 37 16 94 29\n",
"53 71 44 65 25 43 91 52 97 51 14\n",
"70 11 33 28 77 73 17 78 39 68 17 57\n",
"91 71 52 38 17 14 91 43 58 50 27 29 48\n",
"63 66 04 68 89 53 67 30 73 16 69 87 40 31\n",
"04 62 98 27 23 09 70 98 73 93 38 53 60 04 23\n",
"\"\"\""
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def reduce_rows(xs, ys):\n",
" \"\"\" xs is lower row and ys is upper row \"\"\"\n",
" assert(len(xs) == len(ys) + 1)\n",
" return [max([xs[i] + ys[i], xs[i + 1] + ys[i]]) for i in range(len(ys))]\n",
" \n",
"assert(reduce_rows([17, 47, 82], [95, 64]) == [142, 146])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, now all we have to do is the parsing and then a simple fold."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"xss = [list(map(int, xs.split())) for xs in t.split(\"\\n\") if xs]\n",
"xss.reverse()\n",
"from functools import reduce\n",
"s = reduce(reduce_rows, xss[1:], xss[0])[0]\n",
"assert(s == 1074)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, let's put this into a nice function an then solve [problem 67](EulerProblem067) right away."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1074\n"
]
}
],
"source": [
"def find_greatest_path_sum_in_triangle_string(ts):\n",
" from functools import reduce\n",
" xss = [list(map(int, xs.split())) for xs in ts.split(\"\\n\") if xs]\n",
" xss.reverse()\n",
" r = lambda xs, ys: [max([xs[i] + ys[i], xs[i + 1] + ys[i]]) for i in range(len(ys))]\n",
" return reduce(r, xss[1:], xss[0])[0]\n",
"\n",
"print(find_greatest_path_sum_in_triangle_string(t))"
]
}
],
"metadata": {
"completion_date": "Thu, 4 Sep 2014, 20:38",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"fold",
"reduce",
"search"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,158 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 19\n",
"\n",
"You are given the following information, but you may prefer to do some research for yourself.\n",
"\n",
"* 1 Jan 1900 was a Monday.\n",
"* Thirty days has September,\n",
" April, June and November.\n",
" All the rest have thirty-one,\n",
" Saving February alone,\n",
" Which has twenty-eight, rain or shine.\n",
" And on leap years, twenty-nine.\n",
"* A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.\n",
"\n",
"How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I remember someone doing this by estimation. So let's try that first and then code a solution:\n",
"\n",
"We have one hundred years which equal 1200 months. Every month starts with a weekday and $\\frac{1}{7}$ of all weekdays are Sundays. So, 1200 divided by 7 is 171 point something.\n",
"\n",
"Which turns out to be the correct solution.\n",
"\n",
"Let's still code a solution because we were not that smart back then. We create two generators, zip, them and search for 1st and Sunday."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"172\n"
]
}
],
"source": [
"def weekday_generator_function():\n",
" while True:\n",
" yield 'Monday'\n",
" yield 'Tuesday'\n",
" yield 'Wednesday'\n",
" yield 'Thursday'\n",
" yield 'Friday'\n",
" yield 'Saturday'\n",
" yield 'Sunday'\n",
" \n",
"def day_of_month_generator_function():\n",
" day, month, year = 1, 1, 1901\n",
" while year < 2001:\n",
" yield day\n",
" day += 1\n",
" if month == 2:\n",
" if year % 4 == 0 and (not year % 100 == 0 or year % 400 == 0):\n",
" if day == 30:\n",
" month += 1\n",
" day = 1\n",
" elif day == 29:\n",
" month += 1\n",
" day = 1\n",
" elif month in [9, 4, 6, 11] and day == 31:\n",
" day = 1\n",
" month += 1\n",
" elif month in [1, 3, 5, 7, 8, 10] and day == 32:\n",
" day = 1\n",
" month += 1\n",
" elif month == 12 and day == 32:\n",
" day = 1\n",
" month = 1\n",
" year += 1\n",
"\n",
" \n",
"ds = zip(weekday_generator_function(), day_of_month_generator_function())\n",
"s = len([1 for weekday, date in ds if weekday == \"Sunday\" and date == 1])\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, this is actually kind of embarrassing. Why am I even zipping when I have the month right there in my function. Problem is, that my weekday generator starts with Monday, but Monday was the start in 1900 not in 1901. Let's try to do better. 1.1.1901 was a Tuesday, so we drop Monday from the generator."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"171\n"
]
}
],
"source": [
"wds = weekday_generator_function()\n",
"next(wds) # get rid of first Monday\n",
"ds = zip(wds, day_of_month_generator_function())\n",
"s = len([1 for weekday, date in ds if weekday == \"Sunday\" and date == 1])\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And finally, here we go. Actually not a dummy exercise and shows how imporessive the shortcut from the beginning is. Raw power is not always the best solution if we can also use brain."
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 09:56",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"weekdays",
"brain",
"brute force",
"leap year"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,87 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 20\n",
"\n",
"n! means n × (n 1) × ... × 3 × 2 × 1\n",
"\n",
"For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800,\n",
"and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.\n",
"\n",
"Find the sum of the digits in the number 100!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Write our own factorial implementation and get the solution."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def factorial(n):\n",
" assert(n > 0)\n",
" if n == 1:\n",
" return 1\n",
" else:\n",
" return n * factorial(n - 1)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"648\n"
]
}
],
"source": [
"f100 = factorial(100)\n",
"print(sum(map(int, str(f100))))\n",
"assert(sum(map(int, str(f100))) == 648)"
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 10:42",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"factorial"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,427 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 21\n",
"\n",
"Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).\n",
"If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.\n",
"\n",
"For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.\n",
"\n",
"Evaluate the sum of all the amicable numbers under 10000."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We reuse the sieve of eratosthenes (which we called get_primes_smaller previously). What annoys me about the implementation is that we do not stop scanning for prospects once the current prime squared is greater than the limit. Let's test if it returns the same result and compare the execution time."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5.062845234464119\n",
"0.3188800166435408\n"
]
}
],
"source": [
"def get_primes_smaller(limit):\n",
" primes = []\n",
" prospects = [n for n in range(2, limit)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" return primes\n",
"\n",
"def sieve_of_eratosthenes(limit):\n",
" primes = []\n",
" prospects = [n for n in range(2, limit)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > limit:\n",
" break\n",
" primes += prospects\n",
" return primes \n",
"\n",
"import timeit\n",
"import functools\n",
"print(timeit.timeit(functools.partial(get_primes_smaller, 10000), number=100))\n",
"print(timeit.timeit(functools.partial(sieve_of_eratosthenes, 10000), number=100))\n",
"assert(get_primes_smaller(10000) == sieve_of_eratosthenes(10000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, this difference is sick actually. Interesting to see what the difference between O(sqrt(n)) and O(n) can mean. Now we can use the primes to do the factorization. I will again apply some optimizations and see how it turns out"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6.370271180404346\n",
"5.785088868397899\n"
]
}
],
"source": [
"def get_prime_factors_old(number):\n",
" prime_generator = sieve_of_eratosthenes(number // 2)\n",
" remainder = number\n",
" factors = []\n",
" for p in prime_generator:\n",
" while remainder % p == 0:\n",
" remainder //= p\n",
" factors.append(p)\n",
" if remainder == 1 or p * p > number:\n",
" break\n",
" if remainder != 1:\n",
" factors.append(remainder)\n",
" return factors\n",
"\n",
"def get_prime_factors(number):\n",
" remainder = number\n",
" factors = []\n",
" for p in sieve_of_eratosthenes(number // 2):\n",
" while remainder % p == 0:\n",
" remainder //= p\n",
" factors.append(p)\n",
" if remainder == 1:\n",
" break\n",
" if p > remainder or p * p > number:\n",
" factors.append(remainder)\n",
" break\n",
" return factors\n",
"\n",
"import timeit\n",
"import functools\n",
"print(timeit.timeit(functools.partial(get_prime_factors_old, 1000000), number=10))\n",
"print(timeit.timeit(functools.partial(get_prime_factors, 1000000), number=10))\n",
"assert(get_prime_factors_old(100000) == get_prime_factors(100000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, actually no big difference. Kind of expected if you check how similar the implementations are. I though stopping if p is greater than the remainder may be a common case.\n",
"\n",
"Now we can use the prime factors to get all factors. For this each prime number can be used 0 to n times where n is the number how often the prime occurs in the prime factorization. For example, all possible fators for the primes $2, 2, 3$ are $2^0 \\times 3^0, 2^1 \\times 3^0, 2^2 \\times 3^0, 2^0 \\times 3^1, 2^1 \\times 3^1, 2^2 \\times 3^1$ which results in $1, 2, 4, 3, 6, 12$.\n",
"\n",
"So we proceed in the following way. Once we have the prime factors we group then. Then we calculate the factors for each group. For example for $2,2$ the factors would be $1, 2, 4$ as explained in the previous paragraph. Then we calculate the combinations of all factor groups."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def group(xs):\n",
" from functools import reduce\n",
" rs = []\n",
" def f(xss, x):\n",
" if xss and x in xss[-1]:\n",
" xss[-1].append(x)\n",
" else:\n",
" xss.append([x])\n",
" return xss\n",
" return reduce(f, xs, [])\n",
"\n",
"assert(group([1, 2, 2, 2, 4, 4, 5]) == [[1], [2, 2, 2], [4, 4], [5]])\n",
"\n",
"def group(xs):\n",
" r = []\n",
" for x in xs:\n",
" if r and r[-1][0] == x:\n",
" r[-1].append(x)\n",
" else:\n",
" r.append([x])\n",
" return r\n",
"\n",
"assert(group([1, 2, 2, 2, 4, 4, 5]) == [[1], [2, 2, 2], [4, 4], [5]])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As you can see I had a fancy version with reduce first, but the loop is way more readable. We iterate over the input list. If the current item is in the last sublist of the return list we add it to the list. Otherwise we append a new sublist with the item.\n",
"\n",
"Next we write a function that calculates the resulting factors for a factor group."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def prime_group_to_factors(group):\n",
" f = group[0]\n",
" n = len(group)\n",
" return [f**i for i in range(n + 1)]\n",
"\n",
"assert(prime_group_to_factors([2, 2, 2]) == [1, 2, 4, 8])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"No we only have to get all factors by calculating the combination of two factor lists."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def combine_factors(xs, ys):\n",
" return [x * y for y in ys for x in xs]\n",
"\n",
"assert(combine_factors([1, 2, 4], [1, 3]) == [1, 2, 4, 3, 6, 12])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now actually we want to combine an arbitrary number of factor lists."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def combine_factors(xss):\n",
" ys = [1]\n",
" for xs in xss:\n",
" ys = [x * y for y in ys for x in xs]\n",
" return ys"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_divisors(n):\n",
" prime_factors = get_prime_factors(n)\n",
" prime_groups = group(prime_factors)\n",
" factor_groups = list(map(prime_group_to_factors, prime_groups))\n",
" divisors = combine_factors(factor_groups)\n",
" divisors.sort()\n",
" return divisors\n",
" \n",
"assert(get_divisors(220) == [1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110, 220])\n",
"assert(get_divisors(13) == [1, 13])\n",
"assert(get_divisors(26) == [1, 2, 13, 26])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can finally start to get the solution. Remember that we only want to get the sum of proper divisors which are the divisors withouth the number itself."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def sum_of_proper_divisors(number):\n",
" return sum(get_divisors(number)[:-1])\n",
"\n",
"assert(sum_of_proper_divisors(220) == 284)\n",
"assert(sum_of_proper_divisors(284) == 220)\n",
"\n",
"def is_amicable(number):\n",
" s = sum_of_proper_divisors(number)\n",
" if s == number:\n",
" return False\n",
" return number == sum_of_proper_divisors(s)\n",
"\n",
"assert(is_amicable(220))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The if statement is very import because a number pair $a, b$ is only amicable if $a \\neq b$."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"31626\n"
]
}
],
"source": [
"amicable_till_10000 = [i for i in range(1, 10000) if is_amicable(i)]\n",
"assert(sum(amicable_till_10000) == 31626)\n",
"print(sum(amicable_till_10000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I found some brute force solutions in the Euler forum and they claim to have a sick performance. I want to compare them."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"108.68903765424807\n"
]
}
],
"source": [
"def brute_force():\n",
" return sum([i for i in range(1, 10000) if is_amicable(i)])\n",
"\n",
"import timeit\n",
"print(timeit.timeit(brute_force, number=10))"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.7862764837699387\n"
]
}
],
"source": [
"def sum_of_proper_divisors(n):\n",
" from math import sqrt\n",
" s = 1\n",
" for i in range(2, int(sqrt(n)) + 1):\n",
" if n % i == 0:\n",
" s += i\n",
" s += (n // i)\n",
" return s\n",
"\n",
"assert(sum_of_proper_divisors(220) == 284)\n",
" \n",
"def is_amicable(number):\n",
" s = sum_of_proper_divisors(number)\n",
" if s == number:\n",
" return False\n",
" return number == sum_of_proper_divisors(s)\n",
"\n",
"def brute_force():\n",
" return sum([i for i in range(1, 10000) if is_amicable(i)]) \n",
" \n",
"import timeit\n",
"print(timeit.timeit(brute_force, number=10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is actually really embarrassing. Especially I was aware of the sqrt trick all the way but did not manage to put it into use properly. Another example where greate engineer will leave you far behind compared to great thinking.\n",
"\n",
"**Supplement:** Also I have discovered that my sum of proper divisors function has a bug when n is a square, because in that case _i == (n // 1)_ which adds this value two times. So there is no amicable number under 10000 which is also a square because otherwise we would have failed."
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 14:39",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"amicable",
"sieve of eratosthenes",
"factors",
"timeit"
]
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@ -1,126 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 22\n",
"\n",
"Using names.txt (saved as EulerProblem022.txt in the same directory as this notebook), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.\n",
"\n",
"For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.\n",
"\n",
"What is the total of all the name scores in the file?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, this should be straight forward."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"with open('EulerProblem022.txt', 'r') as f:\n",
" names = f.read().split(',')\n",
"\n",
"def get_score_for_name(name):\n",
" return sum([ord(c) - ord('A') + 1 for c in name if not c == '\"'])\n",
"\n",
"assert(get_score_for_name('COLIN') == 53)\n",
"names.sort()\n",
"s = sum([(i + 1) * get_score_for_name(name) for i, name in enumerate(names)])\n",
"assert(s == 871198282)\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I think nothing to explain here. The only question is what was if we hadn't the Python sort function to sort into alphabetical order, then we would have to write our own compare function and use it with what ever sorting algorithm."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arnold before Felix\n",
"Felix before Felixb\n",
"Felix before Felixb\n",
"Felix is Felix\n"
]
}
],
"source": [
"def compare(a, b):\n",
" try:\n",
" for i in range(len(a)):\n",
" if a[i] < b[i]:\n",
" return '{} before {}'.format(a, b)\n",
" elif a[i] > b[i]:\n",
" return '{} before {}'.format(b, a)\n",
" except IndexError:\n",
" pass\n",
" if len(a) < len(b):\n",
" return '{} before {}'.format(a, b)\n",
" elif len(a) > len(b):\n",
" return '{} before {}'.format(b, a)\n",
" else:\n",
" return '{} is {}'.format(b, a)\n",
"\n",
"print(compare('Felix', 'Arnold'))\n",
"print(compare('Felix', 'Felixb'))\n",
"print(compare('Felixb', 'Felix'))\n",
"print(compare('Felix', 'Felix'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Obviously, the algorithm would return True/False or 0/1/-1 for real sorting."
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 15:24",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"sorting",
"lexicographical order"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,141 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 23\n",
"\n",
"A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.\n",
"\n",
"A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.\n",
"\n",
"As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.\n",
"\n",
"Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We reuse the sum of proper divisors function and use it to tell whether a number is abundant or not."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def sum_of_proper_divisors(n):\n",
" from math import sqrt\n",
" if n == 1:\n",
" return 0\n",
" s = 1\n",
" for i in range(2, int(sqrt(n)) + 1):\n",
" if n % i == 0:\n",
" s += i\n",
" x = (n // i)\n",
" if x != i:\n",
" s += x\n",
" return s\n",
"\n",
"def is_abundant(n):\n",
" return sum_of_proper_divisors(n) > n\n",
"\n",
"assert(is_abundant(7) == False)\n",
"assert(is_abundant(12) == True)\n",
"\n",
"abundant_numbers_smaller_30000 = [n for n in range(1, 30001) if is_abundant(n)]\n",
"abundant_numbers_smaller_30000_set = set(abundant_numbers_smaller_30000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that we have all abundant numbers in sorted order we can write a function which tests whether a number can be written as a sum of two abundant numbers."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_sum_of_two_abundants(n):\n",
" for a in abundant_numbers_smaller_30000:\n",
" if a > (n // 2):\n",
" return False\n",
" r = n - a\n",
" if r in abundant_numbers_smaller_30000_set:\n",
" return True\n",
" return False\n",
"\n",
"assert(is_sum_of_two_abundants(24) == True)\n",
"assert(is_sum_of_two_abundants(23) == False)\n",
"assert(is_sum_of_two_abundants(28123) == True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we try to brute force."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4179871\n"
]
}
],
"source": [
"s = sum([i for i in range(1, 30000) if not is_sum_of_two_abundants(i)])\n",
"print(s)\n",
"assert(s == 4179871)"
]
}
],
"metadata": {
"completion_date": "Thu, 5 Nov 2015, 14:48",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"perfect number",
"abundant",
"factors"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,109 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 24 \n",
"\n",
"A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:\n",
"\n",
"012 021 102 120 201 210\n",
"\n",
"What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I tried to solve this by thinking and failed to be hones. So we implement a generator and get the millionth element."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from collections import deque\n",
"\n",
"def permutation_generator(xs):\n",
" if not xs:\n",
" yield deque()\n",
" r = []\n",
" for i in range(len(xs)):\n",
" x = xs[i]\n",
" ys = permutation_generator(xs[:i] + xs[i+1:])\n",
" for y in ys:\n",
" y.appendleft(x)\n",
" yield y\n",
" raise StopIteration\n",
"\n",
"assert(list(map(lambda s: \"\".join(s), permutation_generator(\"012\"))) == ['012', '021', '102', '120', '201', '210'])"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"All right, now we reuse the function to get the nth element from problem 7 and give ourselves a solution."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2783915460\n"
]
}
],
"source": [
"def get_nth(generator, n):\n",
" import itertools\n",
" return next(itertools.islice(generator, n - 1, n))\n",
"\n",
"ps = permutation_generator(\"0123456789\")\n",
"s = int(\"\".join(get_nth(ps, 1000000)))\n",
"assert(s == 2783915460)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Thu, 5 Nov 2015, 16:04",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"permutation"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,100 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 25\n",
"\n",
"The Fibonacci sequence is defined by the recurrence relation:\n",
"\n",
"$F_n = F_{n1} + F_{n2}$, where $F_1 = 1$ and $F_2 = 1$.\n",
"Hence the first 12 terms will be:\n",
"\n",
"~~~\n",
"F1 = 1\n",
"F2 = 1\n",
"F3 = 2\n",
"F4 = 3\n",
"F5 = 5\n",
"F6 = 8\n",
"F7 = 13\n",
"F8 = 21\n",
"F9 = 34\n",
"F10 = 55\n",
"F11 = 89\n",
"F12 = 144\n",
"~~~\n",
"\n",
"The 12th term, $F_{12}$, is the first term to contain three digits.\n",
"\n",
"What is the index of the first term in the Fibonacci sequence to contain 1000 digits?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Reuse fibonacci generator and then straight forward."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4782\n"
]
}
],
"source": [
"def fibonacci_generator():\n",
" a = 0\n",
" b = 1\n",
" yield 1\n",
" while True:\n",
" yield a + b\n",
" a, b = b, (a + b)\n",
" \n",
"for i, f in enumerate(fibonacci_generator()):\n",
" if len(str(f)) >= 1000:\n",
" break\n",
"\n",
"s = i + 1\n",
"assert(s == 4782)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 14:57",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"fibonacci"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,126 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 26\n",
"\n",
"A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:\n",
"\n",
"~~~\n",
"1/2\t = \t0.5\n",
"1/3\t = \t0.(3)\n",
"1/4\t = \t0.25\n",
"1/5\t = \t0.2\n",
"1/6\t = \t0.1(6)\n",
"1/7\t = \t0.(142857)\n",
"1/8\t = \t0.125\n",
"1/9\t = \t0.(1)\n",
"1/10 = \t0.1\n",
"~~~\n",
"\n",
"Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.\n",
"\n",
"Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The trick here is to identify a cycle. The easiest way I see to do this is to memorize the remainders. If we have a remainder that we occurred previously there is a cycle.\n",
"\n",
"Let's consider 1/3. The initial remainder is 10. For ten divided by three the new remainder is again ten (or one times ten). So we have a one-cycle of 3."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_cycle_count(nominator, denominator):\n",
" from itertools import count\n",
" assert(nominator == 1)\n",
" remainders = {}\n",
" remainder = nominator\n",
" results = []\n",
" for i in count():\n",
" result = remainder // denominator\n",
" remainder = remainder % denominator\n",
" results.append(result)\n",
" if remainder in remainders:\n",
" return i - remainders[remainder]\n",
" else:\n",
" remainders[remainder] = i\n",
" if remainder == 0:\n",
" return 0\n",
" remainder *= 10\n",
"\n",
"assert(get_cycle_count(1, 7) == 6)\n",
"assert(get_cycle_count(1, 10) == 0)\n",
"assert(get_cycle_count(1, 6) == 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a simple divison algorithm. The only special thing is the remainder and that we remember when it occurs the first time. If a remainder occurrs for the second time we substract the position and thus have the lenght of the cycle. With this solution we should be efficient enough to brute force."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"983\n"
]
}
],
"source": [
"s = max([(get_cycle_count(1, i), i)for i in range(1, 1000)])\n",
"s = s[1]\n",
"assert(s == 983)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Mon, 9 Nov 2015, 22:11",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"reciprocal",
"division",
"nominator",
"denominator"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,142 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 27\n",
"\n",
"Euler discovered the remarkable quadratic formula:\n",
"\n",
"$n^2 + n + 41$\n",
"\n",
"It turns out that the formula will produce 40 primes for the consecutive integer values 0≤n≤39. However, when $n=40$, $40^2 + 40 + 41 = 40(40+1)+41$ is divisible by $41$, and certainly when $n=41,41^2+41+41$ is clearly divisible by 41.\n",
"\n",
"The incredible formula $n^279n+1601$ was discovered, which produces 80 primes for the consecutive values 0≤n≤79. The product of the coefficients, $79$ and $1601$, is $126479$.\n",
"\n",
"Considering quadratics of the form:\n",
"\n",
"$n^2 + an +b$, where |a|<1000 and |b|≤1000\n",
"\n",
"where |n| is the modulus/absolute value of n e.g. |11|=11 and |4|=4.\n",
"\n",
"Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n=0."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Okay, bruteforcing this complete thing is definitely hard. The interesting thing is that euler provided two examples. If we calculate the primes for both terms we see that there is a certain overlap. This indicates that there is a relation between the two. Sure enough if we put $n-40$ into the first term we get the following.\n",
"\n",
"$(n - 40)^2 + (n - 40) + 41 = n^2 - 80n + 1600 + n - 40 + 41 = n^2 - 79n +1601$\n",
"\n",
"Let's assume that all incredible formulas can be derived by inserting $(n - p)$ into the formula. Of course, what ever value we choose for p the resulting terms must not exceed the boundaries for a or b. We calculate the boundaries.\n",
"\n",
"$(n-p)^2 + (n-p) + 41 = n^2 + n(-2p + 1) + p^2 - p + 41$\n",
"\n",
"Where $(-2p + 1) = a$ and $p^2 -p + 41 = b$. We can now calulate the bounds for a:\n",
"\n",
"$-2p + 1 > -1000 \\rightarrow p < 500.5$\n",
"\n",
"$-2 p + 1 < 1000 \\rightarrow p > -499.5$\n",
"\n",
"And b:\n",
"\n",
"$p^2 - p + 41 <= 1000$\n",
"\n",
"$-30.472 < p < 31.472$\n",
"\n",
"$p^2 - p + 41 >= 1000$ True for $\\forall p \\in \\mathbb{N}$\n",
"\n",
"So now we only have to check for the values p in range(-30, 32). Alternatively, for the example $p = 40$ was used, maybe the next smaller value $p = 31$ yields the correct solution:\n",
"\n",
"$s = a\\times b = (-2 * 31 + 1) * (31^2 - 31 + 41) = -61 \\times 971 = -59231$"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"-59231"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import lru_cache\n",
"\n",
"@lru_cache(maxsize=1000)\n",
"def is_prime(n):\n",
" if n < 2:\n",
" return False\n",
" from math import sqrt\n",
" for s in range(2, int(sqrt(n) + 1)):\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
" \n",
"assert(is_prime(41) == True)\n",
"\n",
"def get_quadratic(n, p):\n",
" return n*n + n * (-2* p + 1) + p*p - p + 41\n",
"\n",
"n_max = 0\n",
"p_max = 0\n",
"\n",
"for p in range(-30, 32):\n",
" for n in range(0, 10000):\n",
" if not is_prime(get_quadratic(n, p)) and n > n_max:\n",
" n_max = n\n",
" p_max = p\n",
" break\n",
"\n",
"p = p_max\n",
"s = (-2 * p + 1) * (p*p - p + 41)\n",
"assert(s == -59231)\n",
"s"
]
}
],
"metadata": {
"completion_date": "Mon, 21 Aug 2017, 21:11",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"quadratic",
"primes",
"formula",
"brain"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,142 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 28\n",
"\n",
"Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:\n",
"\n",
"~~~\n",
"21 22 23 24 25\n",
"20 7 8 9 10\n",
"19 6 1 2 11\n",
"18 5 4 3 12\n",
"17 16 15 14 13\n",
"~~~\n",
"\n",
"$1 + 3 + 5 + 7 + 9 + 13 + 17 + 21 + 25 = 101$\n",
"\n",
"It can be verified that the sum of the numbers on the diagonals is 101.\n",
"\n",
"What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When we know the corner of a certain spiral we can calculate it's total like $f_n = 4 c_n + 6 (n - 1)$. We then only have to update the corner value for each spiral. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"total = 1\n",
"current_corner = 3\n",
"\n",
"for n in range(3, 1002, 2):\n",
" total += 4 * current_corner + 6 * (n - 1)\n",
" current_corner += 4 * n - 2\n",
"\n",
"s = total"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"669171001"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"assert(s == 669171001)\n",
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The only missing piece is how could we calculate the current corner value for a certain n. The series for this is as follows:\n",
"\n",
"$c = 1, 3, 13, 31, 57, 91, 133, 183, 241, \\dots$\n",
"\n",
"With some experimenting it can be seen that\n",
"\n",
"$c_n = (n - 1)^2 - (n - 2) = n^2 - 2n + 1 - n + 2 = n^2 - 3n + 3$.\n",
"\n",
"Now, we can insert $c_n$ into $f_n$ which gives as the sum of corners for the nth spiral:\n",
"\n",
"$f_n = 4n^2 - 12n + 12 + 6n - 6 = 4n^2 - 6n + 6$"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"669171001"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = 1 + sum([4 * n * n - 6 * n + 6 for n in range(3, 1002, 2)])\n",
"assert(s == 669171001)\n",
"s"
]
}
],
"metadata": {
"completion_date": "Wed, 23 Aug 2017, 15:54",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"spiral",
"diagonals"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,74 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 29\n",
"\n",
"Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:\n",
"\n",
"$2^2=4, 2^3=8, 2^4=16, 2^5=32$\n",
"\n",
"$3^2=9, 3^3=27, 3^4=81, 3^5=243$\n",
"\n",
"$4^2=16, 4^3=64, 4^4=256, 4^5=1024$\n",
"\n",
"$5^2=25, 5^3=125, 5^4=625, 5^5=3125$\n",
"\n",
"If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:\n",
"\n",
"$4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125$\n",
"\n",
"How many distinct terms are in the sequence generated by $a^b$ for $2 ≤ a ≤ 100$ and $2 ≤ b ≤ 100$?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9183\n"
]
}
],
"source": [
"s = len(set([a**b for a in range(2, 101) for b in range(2, 101)]))\n",
"assert(s == 9183)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Fri, 25 Aug 2017, 10:03",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"distinct",
"powers"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,83 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 30\n",
"\n",
"Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:\n",
"\n",
"$1634 = 1^4 + 6^4 + 3^4 + 4^4$\n",
"\n",
"$8208 = 8^4 + 2^4 + 0^4 + 8^4$\n",
"\n",
"$9474 = 9^4 + 4^4 + 7^4 + 4^4$\n",
"\n",
"As $1 = 1^4$ is not a sum it is not included.\n",
"\n",
"The sum of these numbers is $1634 + 8208 + 9474 = 19316$.\n",
"\n",
"Find the sum of all the numbers that can be written as the sum of fifth powers of their digits."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is an eays brute force. We look up the fifth powers."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"443839\n"
]
}
],
"source": [
"fifth_power_lookup = {str(i): i**5 for i in range(0,10)}\n",
"\n",
"def is_number_sum_of_fiths_powers_of_digits(n):\n",
" return n == sum([fifth_power_lookup[d] for d in str(n)])\n",
"\n",
"s = sum([i for i in range(1, 1000000) if is_number_sum_of_fiths_powers_of_digits(i) and not i is 1])\n",
"print(s)\n",
"assert(s == 443839)"
]
}
],
"metadata": {
"completion_date": "Fri, 25 Aug 2017, 12:13",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.3"
},
"tags": [
"digit",
"powers",
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,260 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 31\n",
"\n",
"In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation:\n",
"\n",
"1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).\n",
"\n",
"It is possible to make £2 in the following way:\n",
"\n",
"1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p\n",
"\n",
"How many different ways can £2 be made using any number of coins?"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Let's do it non-recursive. Tricky part is to use ceil, otherwise we get wrong ranges for example for $\\frac{50}{20}$."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 1]\n",
"[0, 1, 2]\n"
]
}
],
"source": [
"from math import ceil\n",
"\n",
"print(list(range(50 // 20)))\n",
"print(list(range(ceil(50 / 20))))"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from math import ceil\n",
"\n",
"def calculate():\n",
" r = 200\n",
" c = 0\n",
"\n",
" if r % 200 == 0:\n",
" c += 1\n",
" for p200 in range(ceil(r / 200)):\n",
" r200 = r - p200 * 200\n",
" if r200 % 100 == 0:\n",
" c += 1\n",
" for p100 in range(ceil(r200 / 100)):\n",
" r100 = r200 - p100 * 100\n",
" if r100 % 50 == 0:\n",
" c += 1\n",
" for p50 in range(ceil(r100 / 50)):\n",
" r50 = r100 - p50 * 50\n",
" if r50 % 20 == 0:\n",
" c += 1\n",
" for p20 in range(ceil(r50 / 20)):\n",
" r20 = r50 - p20 * 20\n",
" if r20 <= 0:\n",
" break\n",
" if r20 % 10 == 0:\n",
" c += 1\n",
" for p10 in range(ceil(r20 / 10)):\n",
" r10 = r20 - p10 * 10\n",
" if r10 % 5 == 0:\n",
" c += 1\n",
" for p5 in range(ceil(r10 / 5)):\n",
" r5 = r10 - p5 * 5\n",
" if r5 % 2 == 0:\n",
" c += 1\n",
" for p2 in range(ceil(r5 / 2)):\n",
" r2 = r5 - p2 * 2\n",
" if r2 % 1 == 0:\n",
" c += 1\n",
"\n",
" return c\n",
"\n",
"s = calculate()"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 73682)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I came up with a more concise solution that can be implemented in Scheme. I would like to compare the performance of the solutions."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n"
]
}
],
"source": [
"def count_change(change, coins):\n",
" if not coins:\n",
" return 0\n",
" count = 0\n",
" coin, coins = coins[0], coins[1:]\n",
" for i in range(change // coin + 1):\n",
" if change - i * coin == 0:\n",
" count += 1\n",
" continue\n",
" if change - i * coin < 0:\n",
" break\n",
" count += count_change(change - i * coin, coins)\n",
" return count\n",
"\n",
"def calculate_iterative():\n",
" return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])\n",
"\n",
"s = calculate_iterative()\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.16300111500095227\n",
"11.429953110000497\n"
]
}
],
"source": [
"import timeit\n",
"print(timeit.timeit(calculate, number=10))\n",
"print(timeit.timeit(calculate_iterative, number=10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Turns out I was way smarter than I thought when I have developped calculate. It checks the remainder and by doing that saves a ton of iterations."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"73682\n",
"0.34602016500139143\n"
]
}
],
"source": [
"def count_change(change, coins):\n",
" count = 0\n",
" coin, coins = coins[0], coins[1:]\n",
"\n",
" if change % coin == 0:\n",
" count += 1\n",
" \n",
" if not coins:\n",
" return count\n",
" \n",
" for i in range(ceil(change / coin)):\n",
" count += count_change(change - i * coin, coins)\n",
" return count\n",
"\n",
"def calculate_iterative():\n",
" return count_change(200, [200, 100, 50, 20, 10, 5, 2, 1])\n",
"\n",
"s = calculate_iterative()\n",
"print(s)\n",
"print(timeit.timeit(calculate_iterative, number=10))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Fri, 25 Aug 2017, 13:02",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"recursion",
"coins"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,91 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 32\n",
"\n",
"We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once; for example, the 5-digit number, 15234, is 1 through 5 pandigital.\n",
"\n",
"The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital.\n",
"\n",
"Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital.\n",
"\n",
"HINT: Some products can be obtained in more than one way so be sure to only include it once in your sum."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start by thinking about how many digits are used for multiplicand/multiplier/product. Obviously, the product must have more then three digits. Can it have more then 4 digits? Obviously it can because then there are only four digits for multiplicand and multiplier which is always smaller than ten thousand. So our product must be in the form $12 \\cdot 345 = 5789$. This makes the rest very easy in Python."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"45228"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from itertools import permutations\n",
"\n",
"def is_solution(s):\n",
" a, b, c = int(s[0:2]), int(s[2:5]), int(s[5:])\n",
" if a * b == c:\n",
" return c\n",
" a, b, c = int(s[0:1]), int(s[1:5]), int(s[5:]) \n",
" if a * b == c:\n",
" return c\n",
" return 0\n",
"\n",
"assert(is_solution(\"391867254\") == 7254)\n",
"assert(is_solution(\"391867245\") == 0)\n",
"\n",
"\n",
"s = sum(set([is_solution(\"\".join(p)) for p in permutations(\"123456789\")]))\n",
"assert(s == 45228)\n",
"s"
]
}
],
"metadata": {
"completion_date": "Wed, 30 Aug 2017, 14:25",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"pandigital",
"products"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,172 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 33\n",
"\n",
"The fraction 49/98 is a curious fraction, as an inexperienced mathematician in attempting to simplify it may incorrectly believe that 49/98 = 4/8, which is correct, is obtained by cancelling the 9s.\n",
"\n",
"We shall consider fractions like, 30/50 = 3/5, to be trivial examples.\n",
"\n",
"There are exactly four non-trivial examples of this type of fraction, less than one in value, and containing two digits in the numerator and denominator.\n",
"\n",
"If the product of these four fractions is given in its lowest common terms, find the value of the denominator."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We start write a function which checks if a number is curios and then brute force."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_curious(n, d):\n",
" assert(len(str(n)) == 2 and len(str(d)) == 2)\n",
" if n == d:\n",
" return False\n",
" for i in range(1, 10):\n",
" if str(i) in str(n) and str(i) in str(d):\n",
" try:\n",
" n_ = int(str(n).replace(str(i), \"\"))\n",
" d_ = int(str(d).replace(str(i), \"\"))\n",
" except ValueError:\n",
" return False\n",
" try:\n",
" if n_ / d_ == n / d:\n",
" return True\n",
" except ZeroDivisionError:\n",
" return False\n",
" return False\n",
"\n",
"assert(is_curious(49, 98) == True)\n",
"assert(is_curious(30, 50) == False)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[(16, 64), (19, 95), (26, 65), (49, 98)]"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fs = [(n, d) for n in range(10, 100) for d in range(n, 100) if is_curious(n, d)]\n",
"fs"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"387296/38729600\n"
]
}
],
"source": [
"n = 1\n",
"d = 1\n",
"for n_, d_ in fs:\n",
" n *= n_\n",
" d *= d_\n",
"\n",
"print(\"{}/{}\".format(n, d))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can see that the solution is $100$. But actually it would be nice to calculate the GCD."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"100"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def gcd_euclid(a, b):\n",
" if a == b:\n",
" return a\n",
" elif a > b:\n",
" return gcd_euclid(a - b, b)\n",
" elif a < b:\n",
" return gcd_euclid(a, b - a)\n",
" \n",
"gcd_nd = gcd_euclid(n, d)\n",
"\n",
"s = d // gcd_nd\n",
"assert(s == 100)\n",
"s"
]
}
],
"metadata": {
"completion_date": "Mon, 12 Feb 2018, 17:29",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"gcd",
"curious",
"faction"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,101 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 34\n",
"\n",
"145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.\n",
"\n",
"Find the sum of all numbers which are equal to the sum of the factorial of their digits.\n",
"\n",
"Note: as 1! = 1 and 2! = 2 are not sums they are not included."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The algorithm for checking if a number is curious should be efficient. The more difficult thing is to select the upper bound for the brute force. It can be seen that $9 999 999 < 9! * 7$. Hence we can select $10^7$ as our bound."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from math import factorial\n",
"\n",
"def is_curious(n):\n",
" s = sum([factorial(int(d)) for d in str(n)])\n",
" return n == s\n",
"\n",
"assert(is_curious(145) == True)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"s = sum([n for n in range(3, 10**7) if is_curious(n)])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"40730"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"assert(s == 40730)\n",
"s"
]
}
],
"metadata": {
"completion_date": "Mon, 12 Feb 2018, 17:57",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"factorial",
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,191 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 35\n",
"\n",
"The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.\n",
"\n",
"There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.\n",
"\n",
"How many circular primes are there below one million?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we get all primes into a look-up table. Then we iterate them and check whether they are circular."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_primes_smaller(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > number:\n",
" return primes + prospects\n",
" return primes\n",
"\n",
"ps = get_primes_smaller(1000000)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_combinations(xs):\n",
" if not xs:\n",
" return []\n",
" rs = []\n",
" for i in range(len(xs)):\n",
" yss = get_combinations(xs[:i] + xs[i + 1:])\n",
" if not yss:\n",
" rs.append(xs[i])\n",
" for ys in yss:\n",
" rs.append(xs[i] + ys)\n",
" return rs\n",
"\n",
"assert(get_combinations(\"ab\") == [\"ab\", \"ba\"])"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from itertools import permutations\n",
"prime_set = set(ps)\n",
"\n",
"def is_circular(p):\n",
" cs = permutations(str(p))\n",
" for c in cs:\n",
" if not int(\"\".join(c)) in prime_set:\n",
" return False\n",
" return True\n",
"\n",
"assert(is_circular(\"2\") == True)\n",
"assert(is_circular(\"11\") == True)\n",
"assert(is_circular(\"47\") == False)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False solution 22\n"
]
}
],
"source": [
"s = len([p for p in ps if is_circular(p)])\n",
"print(\"False solution {}\".format(s))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We did not read the problem properly. Cycles are obviously not the same as permutations. If we change that we should get the solution in no time."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def cyles(xs):\n",
" if len(xs) <= 1:\n",
" return xs\n",
" return [xs[i:] + xs[:i] for i in range(len(xs))]\n",
"\n",
"prime_set = set(ps)\n",
"\n",
"def is_circular(p):\n",
" cs = cyles(str(p))\n",
" for c in cs:\n",
" if not int(\"\".join(c)) in prime_set:\n",
" return False\n",
" return True"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"55"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s = len([p for p in ps if is_circular(p)])\n",
"s"
]
}
],
"metadata": {
"completion_date": "Tue, 13 Feb 2018, 09:14",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"circular",
"combinations"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,112 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 36\n",
"\n",
"The decimal number, 585 = $1001001001_2$ (binary), is palindromic in both bases.\n",
"\n",
"Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.\n",
"\n",
"(Please note that the palindromic number, in either base, may not include leading zeros.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This looks like an easy problem to me. Like really easy. Should we try to brute force first?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_palindrome_decimal(n):\n",
" return str(n) == str(n)[::-1]\n",
"\n",
"assert(is_palindrome_decimal(232) == True)\n",
"assert(is_palindrome_decimal(2) == True)\n",
"assert(is_palindrome_decimal(2322) == False)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_palindrome_binary(n):\n",
" s = str(bin(n)[2:])\n",
" return s == s[::-1]\n",
"\n",
"assert(is_palindrome_binary(585) == True)\n",
"assert(is_palindrome_binary(3) == True)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"s = sum([i for i in range(1000000) if is_palindrome_decimal(i) and is_palindrome_binary(i)])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"872187\n"
]
}
],
"source": [
"print(s)"
]
}
],
"metadata": {
"completion_date": "Fri, 11 May 2018, 02:38",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.5"
},
"tags": [
"palindrome",
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,331 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 37\n",
"\n",
"The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.\n",
"\n",
"Find the sum of the only eleven primes that are both truncatable from left to right and right to left.\n",
"\n",
"NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, I would say we start with one digit and work ourselves up. I will start with implementing a function that takes all current solutions (with one digit for example) and then tests all possible new solutions (aka all two digit primes) if the can be truncated to the one digit solutions.\n",
"\n",
"This was complicated. Let's formulate it clearer. We write a function that takes a list of numbers and tests whether they are left/right trunctable to another list of numbers."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_truncatable_numbers(numbers, targets):\n",
" s = set(targets)\n",
" r = []\n",
" for n in numbers:\n",
" left_trunc = int(str(n)[1:])\n",
" right_trunc = int(str(n)[:-1])\n",
" if left_trunc in s and right_trunc in s:\n",
" r.append(n)\n",
" return r\n",
"\n",
"assert(get_truncatable_numbers([37, 77, 83], [2, 3, 5, 7]) == [37, 77])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next function returns a list of all primes with a certain number of digits n. We gonna reuse the sieve from problem 21."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def sieve_of_eratosthenes(limit):\n",
" primes = []\n",
" prospects = [n for n in range(2, limit)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > limit:\n",
" break\n",
" primes += prospects\n",
" return primes\n",
"\n",
"\n",
"def get_primes_with_n_digits(n):\n",
" lower_limit = 10**(n-1) - 1\n",
" upper_limit = 10**n\n",
" primes = sieve_of_eratosthenes(upper_limit)\n",
" primes = [p for p in primes if p > lower_limit]\n",
" return primes\n",
" \n",
"assert(get_primes_with_n_digits(1) == [2, 3, 5, 7])\n",
"assert(len(get_primes_with_n_digits(2)) == 21)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we simply start with all one digit primes and work our way up using the two functions we have created. On the way up we add the numbers to our result list. For example, 97 is already a valid solution even though it is also the subset of a solution with more digits."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[23, 37, 53, 73, 373]\n"
]
}
],
"source": [
"digits = 1\n",
"solutions = get_primes_with_n_digits(digits)\n",
"results = []\n",
"\n",
"while solutions:\n",
" digits += 1\n",
" solutions = get_truncatable_numbers(get_primes_with_n_digits(digits), solutions)\n",
" for s in solutions:\n",
" results.append(s)\n",
" \n",
"print(results)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This are not the eleven numbers we are looking for. The mistake we made is to not differentiate between left truncatable numbers and right truncatable numbers. For example, 397 is truncatable from the left, but not from the right and is still part of a solution. What we want to do is to work up from both directions and then compute the subset. Hence we write to new functions to check for all truncatable numbers from either left or right and then apply the algorithm from above to both of them."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_truncatable_numbers_right(numbers, targets):\n",
" s = set(targets)\n",
" return [n for n in numbers if int(str(n)[:-1]) in s]\n",
"\n",
"def get_truncatable_numbers_left(numbers, targets):\n",
" s = set(targets)\n",
" return [n for n in numbers if int(str(n)[1:]) in s]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's redo the alogirthm."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[]\n",
"[]\n"
]
}
],
"source": [
"digits = 1\n",
"solutions = get_primes_with_n_digits(digits)\n",
"results_left = []\n",
"\n",
"while solutions:\n",
" break\n",
" digits += 1\n",
" solutions = get_truncatable_numbers_left(get_primes_with_n_digits(digits), solutions)\n",
" for s in solutions:\n",
" results.append(s)\n",
" \n",
"print(results_left)\n",
"\n",
"digits = 1\n",
"solutions = get_primes_with_n_digits(digits)\n",
"results_right = []\n",
"\n",
"while solutions:\n",
" break\n",
" digits += 1\n",
" solutions = get_truncatable_numbers_right(get_primes_with_n_digits(digits), solutions)\n",
" for s in solutions:\n",
" results.append(s)\n",
" \n",
"print(results_right)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I added the terminate symbols because this algorithm did not even terminate. This means there are fairly big primes in either direction. We change the approach from bottom up into the other direction. Let's get all primes till a certain value and just check for them. Aka brute force. For this purpose we write a function that takes a number and checks if it is truncatable in both directions."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"primes_till_10000 = set(sieve_of_eratosthenes(10000))\n",
"\n",
"def is_right_truncatable(number, targets):\n",
" try:\n",
" while True:\n",
" number = int(str(number)[:-1])\n",
" if not number in targets:\n",
" return False\n",
" except ValueError:\n",
" return True\n",
"\n",
"assert(is_right_truncatable(3797, primes_till_10000))\n",
"assert(is_right_truncatable(3787, primes_till_10000) == False)\n",
"\n",
"def is_left_truncatable(number, targets):\n",
" try:\n",
" while True:\n",
" number = int(str(number)[1:])\n",
" if not number in targets:\n",
" return False\n",
" except ValueError:\n",
" return True\n",
"\n",
"assert(is_left_truncatable(3797, primes_till_10000))\n",
"assert(is_left_truncatable(3787, primes_till_10000) == False)\n",
"\n",
"def is_truncatable(number, targets):\n",
" if is_left_truncatable(number, targets) and is_right_truncatable(number, targets):\n",
" return True\n",
" return False\n",
"\n",
"assert(is_truncatable(3797, primes_till_10000))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's just go for a brute force till 10k and see what we get."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 3, 5, 7, 23, 37, 53, 73, 313, 317, 373, 797, 3137, 3797]\n"
]
}
],
"source": [
"s = [p for p in primes_till_10000 if is_truncatable(p, primes_till_10000)]\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The one digit numbers are not relevant but this means we got only ten solutions. So we actually have to try all numbers till $10^{6}$. As it turned out we actually have to add one more digit. This is really ugly brute force. I do not like it. But seems like we got a solution."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 3, 5, 7, 23, 37, 53, 73, 313, 317, 373, 797, 3137, 3797, 739397]\n",
"748317\n"
]
}
],
"source": [
"primes_till_100000 = set(sieve_of_eratosthenes(1000000))\n",
"s = [p for p in primes_till_100000 if is_truncatable(p, primes_till_100000)]\n",
"print(s)\n",
"print(sum(s[4:]))\n",
"s = sum(s[4:])\n",
"assert(s == 748317)"
]
}
],
"metadata": {
"completion_date": "Sun, 13 May 2018, 16:46",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.5"
},
"tags": [
"primes",
"truncated"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,271 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 38\n",
"\n",
"Take the number 192 and multiply it by each of 1, 2, and 3:\n",
"\n",
"$192 \\times 1 = 192$\n",
"\n",
"$192 \\times 2 = 384$\n",
"\n",
"$192 \\times 3 = 576$\n",
"\n",
"By concatenating each product we get the 1 to 9 pandigital, 192384576. We will call 192384576 the concatenated product of 192 and (1,2,3)\n",
"\n",
"The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, and 5, giving the pandigital, 918273645, which is the concatenated product of 9 and (1,2,3,4,5).\n",
"\n",
"What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's start by implementing a function which can calculate the concatenated product of a number based on a given $n$."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def get_concatenated_product_of(number, n):\n",
" number = int(number)\n",
" return \"\".join(str(number * (i + 1)) for i in range(n))\n",
"\n",
"assert(get_concatenated_product_of(9, 5) == \"918273645\")\n",
"assert(get_concatenated_product_of(192, 3) == \"192384576\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we need a function that can check if a number is pandigital for the numbers from 1 to 9. The idea is that we generate a validation array for the numbers 1 to 9. Each number maps to a field in the array and we initialize the array with zeros. We then iterate over the input number and increment the respective validation field by one. Afterwards we check if each field in the validation array is one in which case the number is n-pandigital. Otherwise, it is not."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def is_pandigital(number, n=9):\n",
" number_str = str(number)\n",
" validation_array = [0 for _ in range(n)]\n",
" if \"0\" in number_str:\n",
" return False\n",
" for digit in number_str:\n",
" validation_array[ord(digit) - 49] += 1\n",
" for n in validation_array:\n",
" if n != 1:\n",
" return False\n",
" return True\n",
"\n",
"assert(is_pandigital(\"012345678\") == False)\n",
"assert(is_pandigital(\"123\") == False)\n",
"assert(is_pandigital(\"9\") == False)\n",
"assert(is_pandigital(\"123568\") == False)\n",
"assert(is_pandigital(\"987\", 9) == False)\n",
"assert(is_pandigital(\"918273645\"))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This example shows how important it is to add little tests even for simple programs like this. The first example is certainly not 1 to 9 pandigital, but because of negative array indexing in Python it qualifies as True. We solved this problem by adding a simple check for a \"0\" in the number_str."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next step is to check whether a number has the potential to become a 1 to 9 pandigital. The algorithm is essentially the same except this time we return False only if a field in the validation array is greater than 1. This means at least one digit occurs multiple times. Otherwise, the array has still potential to become a pandigital number."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def could_be_pandigital(number, n=9):\n",
" number_str = str(number)\n",
" validation_array = [0 for _ in range(n)]\n",
" if \"0\" in number_str:\n",
" return False\n",
" for digit in number_str:\n",
" validation_array[ord(digit) - 49] += 1\n",
" for n in validation_array:\n",
" if n > 1:\n",
" return False\n",
" return True\n",
"\n",
"assert(could_be_pandigital(\"012345678\") == False)\n",
"assert(could_be_pandigital(\"123\") == True)\n",
"assert(could_be_pandigital(\"9\") == True)\n",
"assert(could_be_pandigital(\"123568\") == True)\n",
"assert(could_be_pandigital(\"987\", 9) == True)\n",
"assert(could_be_pandigital(\"918273645\"))\n",
"assert(could_be_pandigital(\"98233\") == False)\n",
"assert(could_be_pandigital(\"1223\") == False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next function we want is one which checks if a certain number can actually create a concatenated pandigital product of an integer with (1,2, ... , n) where n > 1. For this function we can use all function which we have implemented to this point. We take a number and do a simple brute force starting with n = 2. We return False once the concatenated product cannot be a pandigital anymore. We use the two given examples as tests."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def can_build_concatenated_pandigital_product(number):\n",
" number_str = str(number)\n",
" for n in range(2, 9):\n",
" concatenated_product = get_concatenated_product_of(number_str, n)\n",
" if is_pandigital(concatenated_product):\n",
" return concatenated_product\n",
" if could_be_pandigital(concatenated_product) == False:\n",
" return False\n",
" raise Exception(\"If we got here we have a bug.\")\n",
"\n",
"assert(can_build_concatenated_pandigital_product(9) == \"918273645\")\n",
"assert(can_build_concatenated_pandigital_product(192) == \"192384576\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From here on it is just a matter of bruteforcing. We know that the base number of a higher concatenated pandigital product has to start with a 9. Also we know that the base number cannot have more than 5 digits because $10000 \\times 1, 10000 \\times 2 = 1000020000\" has already more digits than a potential solution. This means we create a list of possible solutions first."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number of possible solutions: 401\n"
]
}
],
"source": [
"possible_solutions = [i for i in range(1, 10000)\n",
" if str(i).startswith(\"9\")\n",
" if not \"0\" in str(i)\n",
" if could_be_pandigital(i)]\n",
"\n",
"print(\"Number of possible solutions: {}\".format(len(possible_solutions)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since this number is actually small enough we filter all base numbers which can produce a concatenated pandigital product."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Number of possible solutions: 4\n"
]
}
],
"source": [
"possible_solutions = [s for s in possible_solutions\n",
" if can_build_concatenated_pandigital_product(s)]\n",
"\n",
"print(\"Number of possible solutions: {}\".format(len(possible_solutions)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, calculate the actual product and print the highest one."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"932718654\n"
]
}
],
"source": [
"s = max(map(int, map(can_build_concatenated_pandigital_product, possible_solutions)))\n",
"assert(s == 932718654)\n",
"print(s)"
]
}
],
"metadata": {
"completion_date": "Sat, 19 May 2018, 23:45",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.5"
},
"tags": [
"concatenated",
"product",
"pandigital"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,148 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 39\n",
"\n",
"If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120.\n",
"\n",
"$\\{20,48,52\\}, \\{24,45,51\\}, \\{30,40,50\\}$\n",
"\n",
"For which value of p ≤ 1000, is the number of solutions maximised?"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"We are looking for right angle triangles so Pythagoras' theorem $a^2 + b^2 = c^2$ can be used. Also it must be true that $a <= b <= c$ is true for every solution. Let's start with a function that tests the given examples."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def is_right_angle_triangle(a, b, c, p):\n",
" if a + b + c != p:\n",
" return False\n",
" if a**2 + b**2 != c**2:\n",
" return False\n",
" return True\n",
"\n",
"given = [(20, 48, 52, 120), (24, 45, 51, 120), (30, 40, 50, 120)]\n",
"for g in given:\n",
" assert(is_right_angle_triangle(*g))\n",
"assert(is_right_angle_triangle(29, 41, 50, 120) == False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This seems bruteforceable. Let's try to find the solutions for p = 120."
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[(30, 40, 50), (24, 45, 51), (20, 48, 52)]\n"
]
}
],
"source": [
"def brute_force(p):\n",
" solutions = [(a,b, p - a - b)\n",
" for b in range(1, p // 2 + 1)\n",
" for a in range(1, b)\n",
" if a*a + b*b == (p - a - b) * (p - a - b)\n",
" ]\n",
" return solutions\n",
"\n",
"print(brute_force(120))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks good. Let's try for all $p <= 1000$."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"solutions = [(len(brute_force(p)), p) for p in range(1, 1001)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Well, not too fast, but also not too slow. Let's get the max and we have our solution."
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"840\n"
]
}
],
"source": [
"s, p = max(solutions)\n",
"print(p)\n",
"assert(p == 840)"
]
}
],
"metadata": {
"completion_date": "Sun, 20 May 2018, 21:16",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"triangle",
"right",
"integer"
]
},
"nbformat": 4,
"nbformat_minor": 1
}

View File

@ -1,118 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Champernowne's constant (Euler Problem 40)\n",
"\n",
"<https://projecteuler.net/problem=40>\n",
"\n",
"An irrational decimal fraction is created by concatenating the positive integers:\n",
"\n",
" 0.123456789101112131415161718192021...\n",
"\n",
"It can be seen that the 12th digit of the fractional part is 1.\n",
"\n",
"If dn represents the nth digit of the fractional part, find the value of the following expression.\n",
"\n",
"$d_{1} × d_{10} × d_{100} × d_{1000} × d_{10000} × d_{100000} × d_{1000000}$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I do not see why we cannot hold $8 bytes \\times 10^{6} = 8 MB$ in memory."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_irrational_fraction(digits_max):\n",
" s = []\n",
" n = 1\n",
" digits = 0\n",
" while digits < digits_max:\n",
" s.append(str(n))\n",
" digits += len(str(n))\n",
" n += 1\n",
" return \"\".join(s)\n",
"\n",
"assert(get_irrational_fraction(20)[12] == \"1\")\n",
"\n",
"f = get_irrational_fraction(1000001)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, we got the fractional. No we get the digits at the different positions and calculate the product. For that purpose we reuse our poduct function from problem 8."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def product(xs):\n",
" from operator import mul\n",
" from functools import reduce\n",
" return reduce(mul, xs, 1)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"210\n"
]
}
],
"source": [
"s = product(map(int, [f[10**i - 1] for i in range(7)]))\n",
"print(s)\n",
"assert(s == 210)"
]
}
],
"metadata": {
"completion_date": "Sun, 20 May 2018, 00:40",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.5",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.5"
},
"tags": [
"champernowne",
"product",
"fraction"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,123 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Pandigital prime (Euler Problem 41)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=41]\n",
"\n",
"We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime.\n",
"\n",
"What is the largest n-digit pandigital prime that exists?"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def expmod(base, exp, m):\n",
" if exp == 0:\n",
" return 1\n",
" if (exp % 2 == 0):\n",
" return (expmod(base, exp // 2, m) ** 2 % m)\n",
" return (base * expmod(base, exp - 1, m) % m)\n",
" \n",
"def expmod_naiv(base, exp, m):\n",
" return base ** exp % m\n",
"\n",
"def fermat_test(n):\n",
" a = n - 3\n",
" return expmod(a, n, n) == a"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert(expmod(2, 100000, 2143) == expmod_naiv(2, 100000, 2143))"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert(fermat_test(2143))"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7652413\n"
]
}
],
"source": [
"import itertools\n",
"\n",
"for pandigital in itertools.permutations(\"7654321\"):\n",
" p = int(\"\".join(pandigital))\n",
" if fermat_test(p):\n",
" s = p\n",
" break\n",
" \n",
"print(s)\n",
"assert(s == 7652413)"
]
}
],
"metadata": {
"completion_date": "Wed, 19 Dec 2018, 20:14",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"pandigital",
"prime",
"fermat",
"test"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,102 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Coded triangle numbers (Euler Problem 42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The nth term of the sequence of triangle numbers is given by, $t_n = \\frac{1}{2}n(n+1)$; so the first ten triangle numbers are:\n",
"\n",
" 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...\n",
"\n",
"By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is 19 + 11 + 25 = 55 = $t_{10}$. If the word value is a triangle number then we shall call the word a triangle word.\n",
"\n",
"Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words? (The file is saved in the same directory as this notebook file as EulerProblem042.txt)"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_words():\n",
" with open(\"EulerProblem042.txt\", \"r\") as f:\n",
" s = f.read()\n",
" words = [w.strip('\"') for w in s.split(\",\")]\n",
" return words\n",
"\n",
"def calculate_word_value(word):\n",
" word = word.upper()\n",
" return sum([ord(letter) - 64 for letter in word])\n",
"\n",
"assert(calculate_word_value(\"sky\") == 55)\n",
"\n",
"def get_triangle_numbers(n):\n",
" return {n * (n + 1) // 2 for n in range(1, 101)}"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"162\n"
]
}
],
"source": [
"triangle_numbers = get_triangle_numbers(100)\n",
"\n",
"s = len([word for word in get_words() if calculate_word_value(word) in triangle_numbers])\n",
"assert(s == 162)\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Thu, 20 Dec 2018, 16:14",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"triangle",
"words"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,173 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Sub-string divisibility (Euler Problem 43)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=43](https://projecteuler.net/problem=43)\n",
"\n",
"The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.\n",
"\n",
"Let $d_1$ be the 1st digit, $d_2$ be the 2nd digit, and so on. In this way, we note the following:\n",
"\n",
"$d_2d_3d_4$=406 is divisible by 2\n",
"\n",
"$d_3d_4d_5$=063 is divisible by 3\n",
"\n",
"$d_4d_5d_6$=635 is divisible by 5\n",
"\n",
"$d_5d_6d_7=357$ is divisible by 7\n",
"\n",
"$d_6d_7d_8=572$ is divisible by 11\n",
"\n",
"$d_7d_8d_9=728$ is divisible by 13\n",
"\n",
"$d_8d_9d_{10} =289$ is divisible by 17\n",
"\n",
"Find the sum of all 0 to 9 pandigital numbers with this property."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We write a function that tests for the sub-string divisibility property. Then we simply brute force."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"def is_sub_string_divisible(s):\n",
" s = \"\".join(s)\n",
" if int(s[1:4]) % 2 != 0:\n",
" return False\n",
" if int(s[2:5]) % 3 != 0:\n",
" return False\n",
" if int(s[3:6]) % 5 != 0:\n",
" return False\n",
" if int(s[4:7]) % 7 != 0:\n",
" return False\n",
" if int(s[5:8]) % 11 != 0:\n",
" return False\n",
" if int(s[6:9]) % 13 != 0:\n",
" return False\n",
" if int(s[7:10]) % 17 != 0:\n",
" return False\n",
" return True\n",
"\n",
"assert(is_sub_string_divisible(\"1406357289\"))\n",
"assert(is_sub_string_divisible(\"1406357298\") == False)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"import itertools\n",
"\n",
"s = sum([int(\"\".join(p)) for p in itertools.permutations(\"0123456789\") if is_sub_string_divisible(p)])"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"16695334890\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 16695334890)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I just want to write my own permutations functions to see that I am able to do it quickly. We pick each element once and combine it with the permutations for the remaining items:"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"def permutations(items):\n",
" items = list(items)\n",
" if not items:\n",
" return [[]]\n",
" perms = []\n",
" for item in items:\n",
" items_new = list(items)\n",
" items_new.remove(item)\n",
" permutations_new = permutations(items_new)\n",
" for perm in permutations_new:\n",
" perms.append([item] + perm)\n",
" return perms\n",
"\n",
"\n",
"assert(permutations([]) == [[]])\n",
"assert(permutations([1]) == [[1]])\n",
"assert(permutations([1,2]) == [[1,2], [2,1]])\n",
"assert(permutations([1,2,3]) == [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]])\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Fri, 21 Dec 2018, 16:28",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"pandigital",
"divisibility",
"permutations"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,137 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Pentagon numbers (Euler Problem 44)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=44](https://projecteuler.net/problem=44)\n",
"\n",
"Pentagonal numbers are generated by the formula, $P_n=n(3n1)/2$. The first ten pentagonal numbers are:\n",
"\n",
" 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...\n",
"\n",
"It can be seen that $P_4 + P_7 = 22 + 70 = 92 = P_8$. However, their difference, 70 22 = 48, is not pentagonal.\n",
"\n",
"Find the pair of pentagonal numbers, $P_j$ and $P_k$, for which their sum and difference are pentagonal and $D = |P_k P_j|$ is minimised; what is the value of D?"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def pentagonal(n):\n",
" return n * (3 * n - 1) // 2\n",
"\n",
"assert(pentagonal(1) == 1)\n",
"assert(pentagonal(4) == 22)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n = 10000\n",
"p = [pentagonal(n) for n in range(1, n)]\n",
"p_set = set(p)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, I was honestly just going for plain brute force here and the first solution that came up was the solution to the problem... Not really happy with that."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"i = 1020, j = 2167, d = 5482660.\n"
]
}
],
"source": [
"for i in range(1, n):\n",
" for j in range(i + 1, n):\n",
" if p[i - 1] + p[j - 1] in p_set and p[j - 1] - p[i - 1] in p_set:\n",
" d = pentagonal(j) - pentagonal(i)\n",
" s = d\n",
" print(\"i = {}, j = {}, d = {}.\".format(i, j, d))"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5482660\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 5482660)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sat, 22 Dec 2018, 22:57",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"pentagonal",
"brute force",
"improve"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,132 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Triangular, pentagonal, and hexagonal (Euler Problem 45)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=45](https://projecteuler.net/problem=45)\n",
"\n",
"Triangle, pentagonal, and hexagonal numbers are generated by the following formulae:\n",
"\n",
"Triangle\t \t$T_n=n(n+1)/2 = 1, 3, 6, 10, 15, ...$\n",
"\n",
"Pentagonal\t \t$P_n=n(3n1)/2 = 1, 5, 12, 22, 35, ...$\n",
"\n",
"Hexagonal\t \t$H_n=n(2n1) = 1, 6, 15, 28, 45, ...$\n",
"\n",
"It can be verified that T285 = P165 = H143 = 40755.\n",
"\n",
"Find the next triangle number that is also pentagonal and hexagonal."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def T(n):\n",
" return n * (n + 1) // 2\n",
"\n",
"assert(T(3) == 6)\n",
"\n",
"def P(n):\n",
" return n * (3 * n - 1) // 2\n",
"\n",
"assert(P(3) == 12)\n",
"\n",
"def H(n):\n",
" return n * (2 * n - 1)\n",
"\n",
"assert(H(3) == 15)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n_max = 100000\n",
"s = 0\n",
"\n",
"T_list = [T(n) for n in range(1, n_max + 1)]\n",
"P_set = {P(n) for n in range(1, n_max + 1)}\n",
"H_set = {H(n) for n in range(1, n_max + 1)}\n",
"\n",
"for n in range(1, n_max + 1):\n",
" if T_list[n - 1] in P_set and T_list[n - 1] in H_set:\n",
" t = T_list[n - 1]\n",
" if t > 40755:\n",
" s = t"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1533776805\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 1533776805)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sat, 22 Dec 2018, 23:17",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"triangular",
"pentagonal",
"hexagonal"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,156 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Goldbach's other conjecture (Euler Problem 46)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=46](https://projecteuler.net/problem=46)\n",
"\n",
"It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square.\n",
"\n",
"$9 = 7 + 2×1^2$\n",
"\n",
"$15 = 7 + 2×2^2$\n",
"\n",
"$21 = 3 + 2×3^2$\n",
"\n",
"$25 = 7 + 2×3^2$\n",
"\n",
"$27 = 19 + 2×2^2$\n",
"\n",
"$33 = 31 + 2×1^2$\n",
"\n",
"It turns out that the conjecture was false.\n",
"\n",
"What is the smallest odd composite that cannot be written as the sum of a prime and twice a square?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, we reuse Fermat's test and brute force. Easy."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def expmod(base, exp, m):\n",
" if exp == 0:\n",
" return 1\n",
" if (exp % 2 == 0):\n",
" return (expmod(base, exp // 2, m) ** 2 % m)\n",
" return (base * expmod(base, exp - 1, m) % m)\n",
"\n",
"def fermat_test(n):\n",
" a = n - 3\n",
" return expmod(a, n, n) == a"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def twice_square(n):\n",
" return 2 * n * n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"n_max = 10000\n",
"twice_squares = [twice_square(n) for n in range(1, n_max + 1)]\n",
"\n",
"def test_conjecture(n):\n",
" for ts in twice_squares:\n",
" if ts > n:\n",
" return False\n",
" if fermat_test(n - ts):\n",
" return True\n",
" \n",
"assert(test_conjecture(33))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"5777\n"
]
}
],
"source": [
"for n in range(3, n_max + 1, 2):\n",
" if not fermat_test(n) and test_conjecture(n) == False:\n",
" s = n\n",
"\n",
"print(s)\n",
"assert(s == 5777)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sat, 22 Dec 2018, 23:39",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"prime",
"goldbach",
"composite",
"square",
"fermat"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,161 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Distinct primes factors (Euler Problem 47)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=47](https://projecteuler.net/problem=47)\n",
"\n",
"The first two consecutive numbers to have two distinct prime factors are:\n",
"\n",
"14 = 2 × 7\n",
"\n",
"15 = 3 × 5\n",
"\n",
"The first three consecutive numbers to have three distinct prime factors are:\n",
"\n",
"644 = 2² × 7 × 23\n",
"\n",
"645 = 3 × 5 × 43\n",
"\n",
"646 = 2 × 17 × 19.\n",
"\n",
"Find the first four consecutive integers to have four distinct prime factors each. What is the first of these numbers?"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[2, 3, 7]\n"
]
}
],
"source": [
"def sieve_of_eratosthenes(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number + 1)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > number:\n",
" break\n",
" return primes + prospects\n",
"\n",
"import math\n",
"\n",
"def get_prime_factors(n):\n",
" ps = sieve_of_eratosthenes(n)\n",
" fs = []\n",
" for p in ps:\n",
" if n % p == 0:\n",
" fs.append(p)\n",
" while n % p == 0:\n",
" n = n // p\n",
" return fs\n",
"\n",
"def trial_division(n):\n",
" a = [] \n",
" if n % 2 == 0:\n",
" a.append(2)\n",
" while n % 2 == 0:\n",
" n //= 2\n",
" f = 3\n",
" while f * f <= n:\n",
" if n % f == 0:\n",
" a.append(f)\n",
" while n % f == 0:\n",
" n //= f\n",
" else:\n",
" f += 2 \n",
" if n != 1:\n",
" a.append(n)\n",
" return a\n",
" \n",
"assert(get_prime_factors(14) == [2, 7])\n",
"assert(get_prime_factors(644) == [2, 7, 23])\n",
"\n",
"print(trial_division(126))"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"134043\n"
]
}
],
"source": [
"s = []\n",
"for n in range(2, 1000000):\n",
" if len(trial_division(n)) == 4:\n",
" s.append(n)\n",
" else:\n",
" s = []\n",
" if len(s) == 4:\n",
" s = s[0]\n",
" break\n",
"\n",
"print(s)\n",
"assert(s == 134043)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 23 Dec 2018, 00:24",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"trial division",
"prime",
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,85 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Self powers (Euler Problem 48)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=48](https://projecteuler.net/problem=48)\n",
"\n",
"The series, $1^1 + 2^2 + 3^3 + ... + 10^{10} = 10405071317$.\n",
"\n",
"Find the last ten digits of the series, $1^1 + 2^2 + 3^3 + ... + 1000^{1000}$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, this would be way harder in C/C++. In every language with long int support it is easy. See the number of people who have solved it."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9110846700\n"
]
}
],
"source": [
"s = int(str(sum([i**i for i in range(1, 1001)]))[-10:])\n",
"assert(s == 9110846700)\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 23 Dec 2018, 00:32",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"brute force",
"self power"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,168 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Prime permutations (Euler Problem 49)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=49](https://projecteuler.net/problem=49)\n",
"\n",
"The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the 4-digit numbers are permutations of one another.\n",
"\n",
"There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit increasing sequence.\n",
"\n",
"What 12-digit number do you form by concatenating the three terms in this sequence?"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def sieve_of_eratosthenes(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > number:\n",
" break\n",
" return primes + prospects\n",
"\n",
"ps = [p for p in sieve_of_eratosthenes(10000) if p > 1000]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"d = {}\n",
"for p in ps:\n",
" s = \"\".join(sorted(str(p)))\n",
" try:\n",
" d[s].append(p)\n",
" except KeyError:\n",
" d[s] = [p]\n",
" \n",
"pss = [value for key, value in d.items() if len(value) >= 3]"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[1487, 4817, 8147], [2969, 6299, 9629]]\n"
]
}
],
"source": [
"def find_increasing_sequence(xs):\n",
" deltas = [(xs[j] - xs[i], i, j)\n",
" for i in range(0, len(xs) - 1)\n",
" for j in range(i + 1, len(xs))\n",
" ]\n",
" d = {}\n",
" for delta, i, j in deltas:\n",
" if delta in d and d[delta][-1] == i:\n",
" d[delta].append(j)\n",
" else:\n",
" d[delta] = [i, j]\n",
" for delta, sequence in d.items():\n",
" if len(sequence) == 3:\n",
" return [xs[index] for index in sequence]\n",
" return []\n",
"\n",
"s = [find_increasing_sequence(ps) for ps in pss if find_increasing_sequence(ps)]\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"296962999629\n"
]
}
],
"source": [
"s = int(\"\".join(map(str, s[1])))\n",
"assert(s == 296962999629)\n",
"print(s)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Congratulations, the answer you gave to problem 49 is correct.\n",
"\n",
"You are the 49654th person to have solved this problem.\n",
"\n",
"Nice work, failx, you've just advanced to Level 2 . \n",
"46903 members (5.43%) have made it this far.\n",
"\n",
"This problem had a difficulty rating of 5%. The highest difficulty rating you have solved remains at 5%. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 23 Dec 2018, 01:10",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"permutations",
"primes",
"sequence"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,167 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Consecutive prime sum (Euler Problem 50)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=50](https://projecteuler.net/problem=50)\n",
"\n",
"The prime 41, can be written as the sum of six consecutive primes:\n",
"\n",
"$41 = 2 + 3 + 5 + 7 + 11 + 13$\n",
"\n",
"This is the longest sum of consecutive primes that adds to a prime below one-hundred.\n",
"\n",
"The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953.\n",
"\n",
"Which prime, below one-million, can be written as the sum of the most consecutive primes?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def sieve_of_eratosthenes(number):\n",
" primes = []\n",
" prospects = [n for n in range(2, number)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > number:\n",
" break\n",
" return primes + prospects\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def find_max_series(start_index, series_list, series_set): \n",
" series_max = series_list[-1]\n",
" total_max = 0\n",
" total = 0 \n",
" for i in range(start_index, len(series_list)):\n",
" total = total + series_list[i]\n",
" if total in series_set:\n",
" length = i - start_index + 1\n",
" total_max = total\n",
" if total > series_max:\n",
" return (length, total_max)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(6, 41)\n"
]
}
],
"source": [
"n_max = 100\n",
"ps = sieve_of_eratosthenes(n_max)\n",
"ps_set = set(ps)\n",
"ps_max = max(ps)\n",
"s = max([x for x in [find_max_series(i, ps, ps_set) for i in range(0, n_max)] if x])\n",
"print(s)\n",
"assert(s[1] == 41)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(21, 953)\n"
]
}
],
"source": [
"n_max = 1000\n",
"ps = sieve_of_eratosthenes(n_max)\n",
"ps_set = set(ps)\n",
"ps_max = max(ps)\n",
"s = max([x for x in [find_max_series(i, ps, ps_set) for i in range(0, n_max)] if x])\n",
"print(s)\n",
"assert(s[0] == 21)\n",
"assert(s[1] == 953)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(543, 997651)\n",
"997651\n"
]
}
],
"source": [
"n_max = 1000000\n",
"ps = sieve_of_eratosthenes(n_max)\n",
"ps_set = set(ps)\n",
"ps_max = max(ps)\n",
"s = max([x for x in [find_max_series(i, ps, ps_set) for i in range(0, n_max)] if x])\n",
"print(s)\n",
"assert(s[1] == 997651)\n",
"print(s[1])"
]
}
],
"metadata": {
"completion_date": "Sun, 23 Dec 2018, 02:38",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"brute force",
"consecutive",
"primes",
"search"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,189 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Prime digit replacements (Euler Problem 51)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=51](https://projecteuler.net/problem=51)\n",
"\n",
"By replacing the 1st digit of the 2-digit number x3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime.\n",
"\n",
"By replacing the 3rd and 4th digits of 56xx3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property.\n",
"\n",
"Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"We start by writing a function that takes a number and returns all possible replacements.\n",
"\n",
"For example 13 will return [\"x3\", \"1x\"].\n",
"\n",
"I actually had a version that simply replace even digits at first, but that does not work for 56333 for example, because you want to get 56xx3 and not 56xxx. So basically, we have to search for all combinations for each digit. I should probably document what each list comprehension does or I will never understand it again. Haha."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['x3', '1x']\n"
]
}
],
"source": [
"from itertools import combinations\n",
"\n",
"def get_replacements(n):\n",
" n = str(n)\n",
" xss= [[i for i in range(0, len(n)) if n[i] == d]\n",
" for d in \"0123456789\"]\n",
" xss = [x \n",
" for xs in xss if xs\n",
" for i in range(1, len(xs) + 1)\n",
" for x in combinations(xs, i)]\n",
" xss = [\"\".join(['x' if i in xs else d for i, d in enumerate(n)])\n",
" for xs in xss]\n",
" return xss\n",
"\n",
"#assert(get_replacements(13) == [\"x3\", \"1x\"])\n",
"print(get_replacements(13))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will use our good old prime generator."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def is_prime(n, smaller_primes):\n",
" for s in smaller_primes:\n",
" if n % s == 0:\n",
" return False\n",
" if s * s > n:\n",
" return True\n",
" return True\n",
"\n",
"def prime_generator_function():\n",
" primes = [2, 3, 5, 7]\n",
" for p in primes:\n",
" yield p\n",
" while True:\n",
" p += 2\n",
" if is_prime(p, primes):\n",
" primes.append(p)\n",
" yield p"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[121313, 222323, 323333, 424343, 525353, 626363, 828383, 929393]\n"
]
}
],
"source": [
"replacements = {}\n",
"ps = prime_generator_function()\n",
"for p in ps:\n",
" for r in get_replacements(p):\n",
" try:\n",
" replacements[r].append(p)\n",
" if len(replacements[r]) == 8:\n",
" print(replacements[r])\n",
" s = replacements[r][0]\n",
" p = 100000000000 # We have found a solution so we go home\n",
" except KeyError:\n",
" replacements[r] = [p]\n",
" if p > 1000000:\n",
" break"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"121313\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 121313)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 23 Dec 2018, 23:47",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"prime",
"combinations",
"replacement"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,147 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Permuted multiples (Euler Problem 52)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=52](https://projecteuler.net/problem=52)\n",
"\n",
"It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order.\n",
"\n",
"Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits."
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"from functools import reduce\n",
"from operator import eq\n",
"\n",
"def get_length(n):\n",
" \"\"\" Returns the number of digits for n.\n",
" Returns wrong result for n = 0. \"\"\"\n",
" length = 0\n",
" while n:\n",
" length += 1\n",
" n //= 10\n",
" return length\n",
"\n",
"assert(get_length(100) == 3)\n",
"\n",
"def get_digits(n):\n",
" d = []\n",
" while n:\n",
" d.append(n % 10)\n",
" n //= 10\n",
" return d\n",
"\n",
"assert(get_digits(213) == [3, 1, 2])\n",
"\n",
"def get_digits_count(n):\n",
" digits_count = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n",
" for d in get_digits(n):\n",
" digits_count[d] += 1\n",
" return digits_count\n",
"\n",
"assert(get_digits_count(1258744) == [0, 1, 1, 0, 2, 1, 0, 1, 1, 0])"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [],
"source": [
"def check_if_multiples_contain_same_digits(n, max_multiple=2):\n",
" n_digits_count = get_digits_count(n)\n",
" n_length = get_length(n)\n",
" n_multiple = n * max_multiple\n",
" while n != n_multiple:\n",
" if n_length != get_length(n_multiple) or n_digits_count != get_digits_count(n_multiple):\n",
" return False\n",
" n_multiple -= n\n",
" return True\n",
"\n",
"assert(check_if_multiples_contain_same_digits(125874))\n",
"assert(check_if_multiples_contain_same_digits(125875) == False)"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [],
"source": [
"for i in range(1, 10000000):\n",
" if check_if_multiples_contain_same_digits(i, 6):\n",
" s = i\n",
" break"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"142857\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 142857)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 02:32",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"digits",
"permutations"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,125 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Combinatoric selections (Euler Problem 53)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=53](https://projecteuler.net/problem=53)\n",
"\n",
"There are exactly ten ways of selecting three from five, 12345:\n",
"\n",
"$123, 124, 125, 134, 135, 145, 234, 235, 245, 345$\n",
"\n",
"In combinatorics, we use the notation, 5C3 = 10.\n",
"\n",
"In general,\n",
"\n",
"$nCr = \\frac{n!}{r!(nr)!}$, where r ≤ n, n! = n×(n1)×...×3×2×1, and 0! = 1.\n",
"\n",
"It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066.\n",
"\n",
"How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are greater than one-million?"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import math\n",
"\n",
"def combinations_naiv(n, r):\n",
" return math.factorial(n) // (math.factorial(r) * math.factorial(n - r))\n",
"\n",
"assert(combinations_naiv(5, 3) == 10)\n",
"assert(combinations_naiv(23, 10) == 1144066)\n",
"assert(combinations_naiv(20, 20) == 1)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"count = 0\n",
"\n",
"for n in range (1, 101):\n",
" for r in range(1, n + 1):\n",
" if combinations_naiv(n, r) > 10**6:\n",
" count += 1\n",
"\n",
"s = count"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4075\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 4075)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 23:29",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"combinatoric",
"selection",
"factorial",
"airplane"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,300 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Problem Name (Euler Problem 54)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way:\n",
"\n",
"* High Card: Highest value card.\n",
"* One Pair: Two cards of the same value.\n",
"* Two Pairs: Two different pairs.\n",
"* Three of a Kind: Three cards of the same value.\n",
"* Straight: All cards are consecutive values.\n",
"* Flush: All cards of the same suit.\n",
"* Full House: Three of a kind and a pair.\n",
"* Four of a Kind: Four cards of the same value.\n",
"* Straight Flush: All cards are consecutive values of same suit.\n",
"* Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.\n",
"* The cards are valued in the order:\n",
"* 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.\n",
"\n",
"If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of eights beats a pair of fives (see example 1 below). But if two ranks tie, for example, both players have a pair of queens, then highest cards in each hand are compared (see example 4 below); if the highest cards tie then the next highest cards are compared, and so on.\n",
"\n",
"Consider the following five hands dealt to two players:\n",
"\n",
"| Hand | \tPlayer 1\t|\tPlayer 2\t| \tWinner |\n",
"|------|------------|-----------|----------|\n",
"| 1\t | \t5H 5C 6S 7S KD Pair of Fives | 2C 3S 8S 8D TD Pair of Eights | Player 2 |\n",
"| 2\t | \t5D 8C 9S JS AC Highest card Ace | 2C 5C 7D 8S QH Highest card Queen | Player 1 |\n",
"| 3\t | \t2D 9C AS AH AC Three Aces | 3D 6D 7D TD QD Flush with Diamonds | Player 2 |\n",
"| 4\t | \t4D 6S 9H QH QC Pair of Queens Highest card Nine | 3D 6D 7H QD QS Pair of Queens Highest card Seven | Player 1 |\n",
"| 5\t | \t2H 2D 4C 4D 4S Full House With Three Fours | 3C 3D 3S 9S 9D Full House with Three Threes | Player 1 |\n",
"\n",
"The file, poker.txt, contains one-thousand random hands dealt to two players.\n",
"Each line of the file contains ten cards (separated by a single space): the\n",
"first five are Player 1's cards and the last five are Player 2's cards. You can\n",
"assume that all hands are valid (no invalid characters or repeated cards), each\n",
"player's hand is in no specific order, and in each hand there is a clear\n",
"winner.\n",
"\n",
"How many hands does Player 1 win?\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's start with some helper functions."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def suit_to_value(suit):\n",
" return {\n",
" \"2\": 2,\n",
" \"3\": 3,\n",
" \"4\": 4,\n",
" \"5\": 5,\n",
" \"6\": 6,\n",
" \"7\": 7,\n",
" \"8\": 8,\n",
" \"9\": 9,\n",
" \"T\": 10,\n",
" \"J\": 11,\n",
" \"Q\": 12,\n",
" \"K\": 13,\n",
" \"A\": 14,\n",
" }[suit]\n",
"\n",
"assert(suit_to_value('K') == 13)\n",
"\n",
"\n",
"def is_flush(colors):\n",
" first_color = colors[0]\n",
" for color in colors:\n",
" if color != first_color:\n",
" return False\n",
" return True\n",
"\n",
"\n",
"assert(is_flush([\"H\", \"H\", \"H\", \"H\", \"H\"]))\n",
"assert(is_flush([\"H\", \"H\", \"D\", \"H\", \"H\"]) == False)\n",
"\n",
"def is_straight(suits):\n",
" suits = sorted(suits)\n",
" first_suit = suits[0]\n",
" for suit in suits[1:]:\n",
" if first_suit + 1 != suit:\n",
" return False\n",
" first_suit = suit\n",
" return True\n",
"\n",
"assert(is_straight([6,3,4,5,7]))\n",
"assert(is_straight([6,3,4,5,8]) == False)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_numbered_groups(ns):\n",
" \"\"\" Takes [0, 3, 0, 3, 1] and returns\n",
" [(2, 3), (2, 0), (1, 1)]\n",
" \"\"\"\n",
" rs = []\n",
" current_group = []\n",
" for n in sorted(ns, reverse=True):\n",
" if not current_group or n in current_group:\n",
" current_group.append(n)\n",
" else:\n",
" rs.append(current_group)\n",
" current_group = [n]\n",
" rs.append(current_group)\n",
" rs = sorted([(len(r), r[0]) for r in rs], reverse=True)\n",
" return rs\n",
"\n",
"assert(get_numbered_groups([0, 3, 0, 3, 1]) == [(2, 3), (2, 0), (1, 1)])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's put that stuff together."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def rank(hand):\n",
" \"\"\" A hand must be provided as a list of two letter strings.\n",
" The first letter is the suit and the second the suit of a card.\n",
" \n",
" The function returns a tuple. The first value represents the hand as an integer\n",
" where 0 means high card and 9 means Straight Flush. The second value is a list of integers\n",
" ranking the value of the respective rank. For example, a Royal Flush would be (9, [14, 13, 12, 11, 10]),\n",
" while 22aqj would be (1, [2, 2, 14, 12, 11]). By doing this we can simply compare to hands\n",
" by first comparing the rank itself and then the list of integers.\n",
" \n",
" We get something like [\"5H\", \"6S\", \"7S\", \"5C\", \"KD\"].\n",
" \"\"\"\n",
" \n",
" suits, colors = zip(*(map(lambda s: (s[0], s[1]), hand)))\n",
" suits = sorted(map(suit_to_value, suits))\n",
"\n",
" flush = is_flush(colors)\n",
" straight = is_straight(suits)\n",
" numbered_suits = get_numbered_groups(suits)\n",
" if flush and straight:\n",
" return [8, numbered_suits]\n",
" if flush:\n",
" return [5, numbered_suits]\n",
" if straight:\n",
" return [4, numbered_suits]\n",
" if numbered_suits[0][0] == 4:\n",
" return [7, numbered_suits]\n",
" if numbered_suits[0][0] == 3 and numbered_suits[1][0] == 2:\n",
" return [6, numbered_suits]\n",
" if numbered_suits[0][0] == 3:\n",
" return [3, numbered_suits]\n",
" if numbered_suits[0][0] == 2 and numbered_suits[1][0] == 2:\n",
" return [2, numbered_suits]\n",
" if numbered_suits[0][0] == 2:\n",
" return [1, numbered_suits]\n",
" return [0, numbered_suits]\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"assert(rank([\"5H\", \"5C\", \"6S\", \"7S\", \"KD\"]) == [1, [(2, 5), (1, 13), (1, 7), (1, 6)]]) # Pair of Fives\n",
"assert(rank([\"5D\", \"8C\", \"9S\", \"JS\", \"AC\"]) == [0, [(1, 14), (1, 11), (1, 9), (1, 8), (1, 5)]]) # Highest card Ace\n",
"assert(rank([\"2D\", \"9C\", \"AS\", \"AH\", \"AC\"]) == [3, [(3, 14), (1, 9), (1, 2)]]) # Three Aces\n",
"assert(rank([\"4D\", \"6S\", \"9H\", \"QH\", \"QC\"]) == [1, [(2, 12), (1, 9), (1, 6), (1, 4)]]) # Pair of Queens Highest card Nine\n",
"assert(rank([\"2H\", \"2D\", \"4C\", \"4D\", \"4S\"]) == [6, [(3, 4), (2, 2)]]) # Full House With Three Fours\n",
"assert(rank([\"2C\", \"3S\", \"8S\", \"8D\", \"TD\"]) == [1, [(2, 8), (1, 10), (1, 3), (1, 2)]]) # Pair of Eights \n",
"assert(rank([\"2C\", \"5C\", \"7D\", \"8S\", \"QH\"]) == [0, [(1, 12), (1, 8), (1, 7), (1, 5), (1, 2)]]) # Highest card Queen \n",
"assert(rank([\"3D\", \"6D\", \"7D\", \"TD\", \"QD\"]) == [5, [(1, 12), (1, 10), (1, 7), (1, 6), (1, 3)]]) # Flush with Diamonds \n",
"assert(rank([\"3D\", \"6D\", \"7H\", \"QD\", \"QS\"]) == [1, [(2, 12), (1, 7), (1, 6), (1, 3)]]) # Pair of Queens Highest card Seven \n",
"assert(rank([\"3C\", \"3D\", \"3S\", \"9S\", \"9D\"]) == [6, [(3, 3), (2, 9)]]) # Full House with Three Threes \n"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def read_hands():\n",
" \"\"\" Reads a list of tuples where each field\n",
" in the tuple represents a hand.\n",
" \"\"\"\n",
" hands = []\n",
" with open(\"EulerProblem054.txt\", \"r\") as f:\n",
" for line in f.readlines():\n",
" cards = line.strip().split(\" \")\n",
" hands.append((cards[:5], cards[5:]))\n",
" return hands\n",
"\n",
"p1_wins = 0\n",
"\n",
"for p1_hand, p2_hand in read_hands():\n",
" if rank(p1_hand) > rank(p2_hand):\n",
" p1_wins += 1\n",
" msg = \"P1 hand {} wins over P2 hand {}.\"\n",
" #print(msg.format(p1_hand, p2_hand))\n",
" else:\n",
" msg = \"P1 hand {} loses versus P2 hand {}.\"\n",
" #print(msg.format(p1_hand, p2_hand))\n",
" \n",
"s = p1_wins "
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"376\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 376)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 23:30",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"poker",
"airplane"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,159 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Lychrel numbers (Euler Problem 55)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=55](https://projecteuler.net/problem=55)\n",
"\n",
"If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.\n",
"\n",
"Not all numbers produce palindromes so quickly. For example,\n",
"\n",
"$349 + 943 = 1292$\n",
"\n",
"$1292 + 2921 = 4213$\n",
"\n",
"$4213 + 3124 = 7337$\n",
"\n",
"That is, 349 took three iterations to arrive at a palindrome.\n",
"\n",
"Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).\n",
"\n",
"Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.\n",
"\n",
"How many Lychrel numbers are there below ten-thousand?\n",
"\n",
"NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_digits(n):\n",
" d = []\n",
" while n:\n",
" d.append(n % 10)\n",
" n //= 10\n",
" return d\n",
"\n",
"def is_pilandrome(n):\n",
" ds = get_digits(n)\n",
" len_ds = len(ds)\n",
" if len_ds < 2:\n",
" return True\n",
" for i in range(0, len_ds // 2):\n",
" if ds[i] != ds[len_ds - i - 1]:\n",
" return False\n",
" return True\n",
"\n",
"assert(is_pilandrome(1337) == False)\n",
"assert(is_pilandrome(1331))\n",
"assert(is_pilandrome(131))\n",
"assert(is_pilandrome(132) == False)\n",
"\n",
"\n",
"def get_digit_inverse(n):\n",
" ds = get_digits(n)\n",
" base = 1\n",
" i = 0\n",
" for d in ds[::-1]:\n",
" i += (base * d)\n",
" base *= 10\n",
" return i\n",
"\n",
"assert(get_digit_inverse(47) == 74)\n",
"assert(get_digit_inverse(47) == 74)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def is_not_lychrel(n, iterations=50):\n",
" for i in range(0, iterations):\n",
" n = n + get_digit_inverse(n)\n",
" if is_pilandrome(n):\n",
" return (i + 1)\n",
" return 0\n",
"\n",
"assert(is_not_lychrel(47) == 1)\n",
"assert(is_not_lychrel(349) == 3)\n",
"assert(is_not_lychrel(10677, 100) == 53)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"249\n"
]
}
],
"source": [
"lychrels = [n for n in range(1, 10000) if is_not_lychrel(n) == 0]\n",
"s = len(lychrels)\n",
"print(s)\n",
"assert(s == 249)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 23:32",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"lychrel",
"airplane"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,95 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Powerful digit sum (Euler Problem 56)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"A googol ($10^{100}$) is a massive number: one followed by one-hundred zeros; $100^{100}$ is almost unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.\n",
"\n",
"Considering natural numbers of the form, $a^b$, where $a, b < 100$, what is the maximum digital sum?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_digit_sum(n):\n",
" s = 0\n",
" while n != 0:\n",
" s += (n % 10)\n",
" n //= 10\n",
" return s\n",
"\n",
"assert(get_digit_sum(1337) == 14)\n",
"assert(get_digit_sum(100**100) == 1)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"972\n"
]
}
],
"source": [
"s = max([get_digit_sum(a**b) for a in range(1, 100) for b in range(1, 100)])\n",
"print(s)\n",
"assert(s == 972)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 23:33",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"power",
"brute force"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,155 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Square root convergents (Euler Problem 57)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=57](https://projecteuler.net/problem=57)\n",
"\n",
"It is possible to show that the square root of two can be expressed as an infinite continued fraction.\n",
"\n",
"√ 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213...\n",
"\n",
"By expanding this for the first four iterations, we get:\n",
"\n",
"1 + 1/2 = 3/2 = 1.5\n",
"\n",
"1 + 1/(2 + 1/2) = 7/5 = 1.4\n",
"\n",
"1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...\n",
"\n",
"1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...\n",
"\n",
"The next three expansions are 99/70, 239/169, and 577/408, but the eighth expansion, 1393/985, is the first example where the number of digits in the numerator exceeds the number of digits in the denominator.\n",
"\n",
"In the first one-thousand expansions, how many fractions contain a numerator with more digits than denominator?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_digit_count(n):\n",
" c = 0\n",
" while n:\n",
" c += 1\n",
" n //= 10\n",
" return c\n",
"\n",
"assert(get_digit_count(1337) == 4)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def gcd(a, b):\n",
" if b > a:\n",
" a, b = b, a\n",
" while a % b != 0:\n",
" a, b = b, a % b\n",
" return b\n",
" \n",
"assert(gcd(100, 35) == 5)\n",
"\n",
"def add_fractions(n1, d1, n2, d2):\n",
" d = d1 * d2\n",
" n1 = n1 * (d // d1)\n",
" n2 = n2 * (d // d2)\n",
" n = n1 + n2\n",
" p = gcd(n, d)\n",
" return (n // p, d // p)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def next_expension(n, d):\n",
" n, d = add_fractions(1, 1, n, d)\n",
" return add_fractions(1, 1, d, n)\n",
"\n",
"c = 0\n",
"\n",
"n, d = (3, 2)\n",
"for i in range(1000):\n",
" if get_digit_count(n) > get_digit_count(d):\n",
" c += 1\n",
" n, d = next_expension(n, d)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"153\n"
]
}
],
"source": [
"s = c\n",
"print(s)\n",
"assert(s == 153)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 24 Dec 2018, 23:35",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"square root",
"gcd",
"airplane",
"fractions"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,353 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Spiral primes (Euler Problem 58)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=58](https://projecteuler.net/problem=58)\n",
"\n",
"Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.\n",
"\n",
" 37 36 35 34 33 32 31\n",
" 38 17 16 15 14 13 30\n",
" 39 18 5 4 3 12 29\n",
" 40 19 6 1 2 11 28\n",
" 41 20 7 8 9 10 27\n",
" 42 21 22 23 24 25 26\n",
" 43 44 45 46 47 48 49\n",
"\n",
"It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that 8 out of the 13 numbers lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.\n",
"\n",
"If one complete new layer is wrapped around the spiral above, a square spiral with side length 9 will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_last_corner_value(side_length):\n",
" return side_length * side_length\n",
"\n",
"assert(get_last_corner_value(1) == 1)\n",
"assert(get_last_corner_value(3) == 9)\n",
"assert(get_last_corner_value(5) == 25)\n",
"\n",
"\n",
"def get_corner_values(side_length):\n",
" if side_length == 1:\n",
" return [1]\n",
" return [get_last_corner_value(side_length) - i * (side_length - 1)\n",
" for i in range(0, 4)][::-1]\n",
"\n",
"assert(get_corner_values(1) == [1])\n",
"assert(get_corner_values(3) == [3, 5, 7, 9])\n",
"assert(get_corner_values(5) == [13, 17, 21, 25])\n",
"assert(get_corner_values(7) == [31, 37, 43, 49])\n",
"\n",
"\n",
"def get_diagonal_values(side_length):\n",
" return [corner_value\n",
" for length in range(1, side_length + 1, 2)\n",
" for corner_value in get_corner_values(length)\n",
" ]\n",
"\n",
"assert(get_diagonal_values(1) == [1])\n",
"assert(get_diagonal_values(3) == [1, 3, 5, 7, 9])\n",
"assert(get_diagonal_values(5) == [1, 3, 5, 7, 9, 13, 17, 21, 25])"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def expmod(base, exp, m):\n",
" if exp == 0:\n",
" return 1\n",
" if (exp % 2 == 0):\n",
" return (expmod(base, exp // 2, m) ** 2 % m)\n",
" return (base * expmod(base, exp - 1, m) % m)\n",
" \n",
"\n",
"def fermat_test_sicp(n):\n",
" if n < 40:\n",
" return n in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39]\n",
" a = n - 3\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 5\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 7\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 11\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 13\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 17\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 19\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 23\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 29\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 31\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 37\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" a = n - 39\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" return True\n",
"\n",
"def trial_division(n):\n",
" a = [] \n",
" if n % 2 == 0:\n",
" a.append(2)\n",
" while n % 2 == 0:\n",
" n //= 2\n",
" f = 3\n",
" while f * f <= n:\n",
" if n % f == 0:\n",
" a.append(f)\n",
" while n % f == 0:\n",
" n //= f\n",
" else:\n",
" f += 2 \n",
" if n != 1:\n",
" a.append(n)\n",
" return a\n",
"\n",
"def is_prime(n):\n",
" if n == 1:\n",
" return False\n",
" return trial_division(n)[0] == n\n",
"\n",
"assert(fermat_test_sicp(3))\n",
"assert(fermat_test_sicp(107))\n",
"assert(fermat_test_sicp(108) == False)\n",
"assert(fermat_test_sicp(109))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"n: 26241 count_total: 52481 count_primes: 5248 ratio: 0.09999809454850327\n"
]
}
],
"source": [
"def get_solution():\n",
" n = 1\n",
" count_primes = 0\n",
" count_total = 0\n",
" while True:\n",
" for v in get_corner_values(n):\n",
" count_total += 1\n",
" if is_prime(v):\n",
" count_primes += 1\n",
" ratio = count_primes / count_total\n",
" if ratio != 0 and ratio < 0.10:\n",
" print(\"n: {} count_total: {} count_primes: {} ratio: {}\".format(n, count_total, count_primes, ratio))\n",
" return n\n",
" n += 2\n",
"\n",
"s = get_solution()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"26241\n"
]
}
],
"source": [
"print(s)\n",
"assert(s == 26241)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I actually got different results for the Fermat test and for the prime test which relies on reliable computation. I will actually try to solve the problem with ramdonized Fermat test now."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"n: 26641 count_total: 53281 count_primes: 5328 ratio: 0.09999812315834913\n",
"26641\n",
"Expected n is 26241.\n"
]
}
],
"source": [
"import random\n",
"\n",
"def is_prime(n):\n",
" if n == 1:\n",
" return False\n",
" for _ in range(10):\n",
" a = n - random.randint(1, n - 1)\n",
" if not expmod(a, n, n) == a:\n",
" return False\n",
" return True\n",
"\n",
"print(get_solution())\n",
"print(\"Expected n is 26241.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Something seems to be off with my Fermat test... \n",
"\n",
"Seems like there are systematic errors with the Fermat tests. Certain primes cannot be deteced.\n",
"\n",
"Try this algorithm instead [https://en.wikipedia.org/wiki/MillerRabin_primality_test](https://en.wikipedia.org/wiki/MillerRabin_primality_test)."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"n: 26241 count_total: 52481 count_primes: 5248 ratio: 0.09999809454850327\n",
"26241\n",
"For 561 sicp says True and real test says False.\n",
"For 1105 sicp says True and real test says False.\n",
"For 1729 sicp says True and real test says False.\n",
"For 2465 sicp says True and real test says False.\n",
"For 2821 sicp says True and real test says False.\n",
"For 6601 sicp says True and real test says False.\n"
]
}
],
"source": [
"carmichael_number = [561, 1105, 1729, 2465, 2821, 6601]\n",
"\n",
"def little_fermat(a, p): # SICP uses this\n",
" return (a ** p) % p == a % p\n",
"\n",
"def little_fermat_simple(a, p): # Wikipedia uses this\n",
" assert(a < p)\n",
" return (a ** (p - 1)) % p == 1\n",
"\n",
"def expmod(base, exp, m):\n",
" if exp == 0:\n",
" return 1\n",
" if (exp % 2 == 0):\n",
" return (expmod(base, exp // 2, m) ** 2 % m)\n",
" return (base * expmod(base, exp - 1, m) % m)\n",
"\n",
"def fermat_test(n):\n",
" ps = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39]\n",
" if n <= ps[-1]:\n",
" return n in ps\n",
" for a in ps:\n",
" #if not little_fermat_simple(a, n):\n",
" if expmod(a, n - 1, n) != 1:\n",
" #print(\"Fermat witness for {} is {}.\".format(n + 1, a))\n",
" return False\n",
" return True\n",
"\n",
"def is_prime(n):\n",
" return fermat_test(n)\n",
"\n",
"print(get_solution())\n",
"\n",
"for n in carmichael_number:\n",
" r_sicp = fermat_test_sicp(n)\n",
" r = fermat_test(n)\n",
" print(\"For {} sicp says {} and real test says {}.\".format(n, r_sicp, r))\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sat, 29 Dec 2018, 09:00",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"prime",
"fermat",
"spiral",
"diagonal",
"todo"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,196 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# XOR decryption (Euler Problem 59)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=59](https://projecteuler.net/problem=59)\n",
"\n",
"Each character on a computer is assigned a unique code and the preferred standard is ASCII (American Standard Code for Information Interchange). For example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107.\n",
"\n",
"A modern encryption method is to take a text file, convert the bytes to ASCII, then XOR each byte with a given value, taken from a secret key. The advantage with the XOR function is that using the same encryption key on the cipher text, restores the plain text; for example, 65 XOR 42 = 107, then 107 XOR 42 = 65.\n",
"\n",
"For unbreakable encryption, the key is the same length as the plain text message, and the key is made up of random bytes. The user would keep the encrypted message and the encryption key in different locations, and without both \"halves\", it is impossible to decrypt the message.\n",
"\n",
"Unfortunately, this method is impractical for most users, so the modified method is to use a password as a key. If the password is shorter than the message, which is likely, the key is repeated cyclically throughout the message. The balance for this method is using a sufficiently long password key for security, but short enough to be memorable.\n",
"\n",
"Your task has been made easy, as the encryption key consists of three lower case characters. Using cipher.txt (right click and 'Save Link/Target As...'), a file containing the encrypted ASCII codes, and the knowledge that the plain text must contain common English words, decrypt the message and find the sum of the ASCII values in the original text."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_encrypted_msg():\n",
" with open(\"EulerProblem059.txt\", \"r\") as f:\n",
" msg = [int(d) for d in f.read().split(',')]\n",
" return msg\n",
" \n",
"def get_words():\n",
" with open(\"EulerProblem042.txt\", \"r\") as f:\n",
" words = [w.strip('\"') for w in f.read().split(\",\")]\n",
" return set(words)\n",
"\n",
"assert(65 ^ 42 == 107)\n",
"msg = get_encrypted_msg()\n",
"word_list = get_words()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We only have a three leter code which makes this problem easy to solve. Normally, "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def generate_keys():\n",
" alphabet = list(map(chr, range(97, 123)))\n",
" return [(ord(a), ord(b), ord(c)) for a in alphabet for b in alphabet for c in alphabet]\n",
"\n",
"keys = generate_keys()\n",
"assert(len(keys) == 26 * 26 * 26)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def to_string(msg):\n",
" return \"\".join(map(chr, msg))\n",
"\n",
"assert(to_string([65, 42, 107]) == \"A*k\")\n",
"\n",
"def to_ascii(msg):\n",
" return list(map(ord, msg))\n",
"\n",
"assert(to_ascii(\"A*k\") == [65, 42, 107])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def decrypt_msg(key, msg):\n",
" return [d ^ key[i % len(key)] for i, d in enumerate(msg)]\n",
"\n",
"assert(decrypt_msg([1, 2, 3], [1, 2, 3, 4, 5, 7]) == [0, 0, 0, 5, 7, 4])\n",
"\n",
"def clean_word(word):\n",
" return word.strip('').strip(\",\").strip(\".\").strip(\"!\").strip(\"?\").upper()\n",
"\n",
"def test_key(key, msg):\n",
" msg = to_string(decrypt_msg(key, msg))\n",
" word_count = 0\n",
" words = msg.split(\" \")\n",
" for word in words:\n",
" if clean_word(word) in word_list:\n",
" word_count += 1 \n",
" return word_count / len(words)\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"ss = [(test_key(key, msg), key) for key in keys]\n",
"s = sorted(ss, reverse=True)[0]\n",
"key = s[1]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(The Gospel of John, chapter 1) 1 In the beginning the Word already existed. He was with God, and he was God. 2 He was in the beginning with God. 3 He created everything there is. Nothing exists that he didn't make. 4 Life itself was in him, and this life gives light to everyone. 5 The light shines through the darkness, and the darkness can never extinguish it. 6 God sent John the Baptist 7 to tell everyone about the light so that everyone might believe because of his testimony. 8 John himself was not the light; he was only a witness to the light. 9 The one who is the true light, who gives light to everyone, was going to come into the world. 10 But although the world was made through him, the world didn't recognize him when he came. 11 Even in his own land and among his own people, he was not accepted. 12 But to all who believed him and accepted him, he gave the right to become children of God. 13 They are reborn! This is not a physical birth resulting from human passion or plan, this rebirth comes from God.14 So the Word became human and lived here on earth among us. He was full of unfailing love and faithfulness. And we have seen his glory, the glory of the only Son of the Father.\n"
]
}
],
"source": [
"print(to_string(decrypt_msg(key, msg)))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"107359\n"
]
}
],
"source": [
"s = sum(decrypt_msg(key, msg))\n",
"print(s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sat, 5 Jan 2019, 00:10",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"xor",
"cipher",
"encryption"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,185 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Prime pair sets (Euler Problem 60)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=60](https://projecteuler.net/problem=60)\n",
"\n",
"The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.\n",
"\n",
"Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[3, 7], [7, 3], [3, 109], [109, 3], [3, 673], [673, 3], [7, 109], [109, 7], [7, 673], [673, 7], [109, 673], [673, 109]]\n"
]
}
],
"source": [
"from itertools import combinations\n",
"\n",
"def concatenate_all(numbers):\n",
" result = []\n",
" for a, b in combinations(numbers, 2):\n",
" result.append([a, b])\n",
" result.append([b, a])\n",
" return result\n",
"\n",
"print(concatenate_all([3, 7, 109, 673]))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def sieve_of_eratosthenes(limit):\n",
" primes = []\n",
" prospects = [n for n in range(2, limit)]\n",
" while prospects:\n",
" p = prospects[0]\n",
" prospects = [x for x in prospects if x % p != 0]\n",
" primes.append(p)\n",
" if p * p > limit:\n",
" break\n",
" primes += prospects\n",
" return primes\n",
"\n",
"primes = sieve_of_eratosthenes(100000)\n",
"primes_set = set(primes)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def is_prime(n):\n",
" if n % 2 == 0:\n",
" return False\n",
" while n % 2 == 0:\n",
" n //= 2\n",
" f = 3\n",
" while f * f <= n:\n",
" if n % f == 0:\n",
" return False\n",
" else:\n",
" f += 2 \n",
" return True\n",
"\n",
"def concatentation_is_prime(a, b):\n",
" ab = int(str(a) + str(b))\n",
" ba = int(str(b) + str(a))\n",
" if is_prime(ab) and is_prime(ba):\n",
" return True\n",
" else:\n",
" return False\n",
" \n",
"assert(concatentation_is_prime(673, 3))\n",
"assert(concatentation_is_prime(673, 1) == False)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[13, 5197, 5701, 6733, 8389]\n",
"26033\n"
]
}
],
"source": [
"potentials = []\n",
"new_potentials = []\n",
"done = False\n",
"for p in primes:\n",
" if done:\n",
" break\n",
" potentials += new_potentials\n",
" new_potentials = []\n",
" for potential in potentials:\n",
" all_concatenations_prime = True\n",
" for prime in potential:\n",
" if not concatentation_is_prime(p, prime):\n",
" all_concatenations_prime = False\n",
" break\n",
" if all_concatenations_prime:\n",
" new_potential = list(potential)\n",
" new_potential.append(p)\n",
" if len(new_potential) > 4:\n",
" print(new_potential)\n",
" s = sum(new_potential)\n",
" done = True\n",
" break\n",
" new_potentials.append(new_potential)\n",
" if p < 15:\n",
" potentials.append([p])\n",
"\n",
"print(s)\n",
"assert(s == 26033)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 6 Jan 2019, 05:00",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"prime",
"pairs"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,163 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Cyclical figurate numbers (Euler Problem 61)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=61](https://projecteuler.net/problem=61)\n",
"\n",
"Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:\n",
"\n",
"Triangle\t \tP3,n=n(n+1)/2\t \t1, 3, 6, 10, 15, ...\n",
"\n",
"Square\t \tP4,n=n2\t \t1, 4, 9, 16, 25, ...\n",
"\n",
"Pentagonal\t \tP5,n=n(3n1)/2\t \t1, 5, 12, 22, 35, ...\n",
"\n",
"Hexagonal\t \tP6,n=n(2n1)\t \t1, 6, 15, 28, 45, ...\n",
"\n",
"Heptagonal\t \tP7,n=n(5n3)/2\t \t1, 7, 18, 34, 55, ...\n",
"\n",
"Octagonal\t \tP8,n=n(3n2)\t \t1, 8, 21, 40, 65, ...\n",
"\n",
"The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.\n",
"\n",
"The set is cyclic, in that the last two digits of each number is the first two digits of the next number (including the last number with the first).\n",
"Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and pentagonal (P5,44=2882), is represented by a different number in the set.\n",
"This is the only set of 4-digit numbers with this property.\n",
"Find the sum of the only ordered set of six cyclic 4-digit numbers for which each polygonal type: triangle, square, pentagonal, hexagonal, heptagonal, and octagonal, is represented by a different number in the set."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_four_digit_numbers(function):\n",
" r = []\n",
" n = 1\n",
" f = function\n",
" while f(n) < 10000:\n",
" if f(n) > 999:\n",
" r.append(f(n))\n",
" n += 1\n",
" return r\n",
"\n",
"triangles = get_four_digit_numbers(lambda n: n * (n + 1) // 2)\n",
"squares = get_four_digit_numbers(lambda n: n**2)\n",
"pentas = get_four_digit_numbers(lambda n: n * (3 * n - 1) // 2)\n",
"hexas = get_four_digit_numbers(lambda n: n * (2 * n - 1))\n",
"heptas = get_four_digit_numbers(lambda n: n * (5*n - 3) // 2)\n",
"octas = get_four_digit_numbers(lambda n: n * (3*n - 2))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def is_cyclic(a, b):\n",
" return str(a)[-2:] == str(b)[:2]\n",
"\n",
"assert(is_cyclic(3328, 2877))\n",
"assert(is_cyclic(3329, 2877) == False)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[8256, 5625, 2512, 1281, 8128, 2882]\n",
"28684\n"
]
}
],
"source": [
"def search_solution(aggregator, polygonals):\n",
" if not polygonals:\n",
" if is_cyclic(aggregator[-1], aggregator[0]):\n",
" return aggregator\n",
" else:\n",
" return []\n",
"\n",
" if not aggregator:\n",
" for polygonal in polygonals:\n",
" for number in polygonal:\n",
" aggregator.append(number)\n",
" s = search_solution(aggregator, [p for p in polygonals if p != polygonal])\n",
" if s:\n",
" return s\n",
" aggregator.pop()\n",
"\n",
" for polygonal in polygonals:\n",
" for number in polygonal:\n",
" if is_cyclic(aggregator[-1], number) and not number in aggregator:\n",
" aggregator.append(number)\n",
" s = search_solution(aggregator, [p for p in polygonals if p != polygonal])\n",
" if s:\n",
" return s\n",
" aggregator.pop()\n",
" return []\n",
"\n",
"s = search_solution([], [triangles, squares, pentas, hexas, heptas, octas])\n",
"print(s)\n",
"s = sum(s)\n",
"print(s)\n",
"assert(s == 28684)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 6 Jan 2019, 05:32",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"search",
"cyclic"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,103 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Cubic permutations (Euler Problem 62)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=62](https://projecteuler.net/problem=62)\n",
"\n",
"The cube, 41063625 (3453), can be permuted to produce two other cubes: 56623104 (3843) and 66430125 (4053). In fact, 41063625 is the smallest cube which has exactly three permutations of its digits which are also cube.\n",
"\n",
"Find the smallest cube for which exactly five permutations of its digits are cube."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"cubes = [n * n * n for n in range(1, 5000)]\n",
"cubes_set = set(cubes)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[127035954683, 352045367981, 373559126408, 569310543872, 589323567104]\n",
"127035954683\n"
]
}
],
"source": [
"solutions = {}\n",
"\n",
"for n in range(1, 10000):\n",
" cube = n * n * n\n",
" try:\n",
" key = \"\".join(sorted(str(cube)))\n",
" solutions[key].append(cube)\n",
" if len(solutions[key]) > 4:\n",
" print(solutions[key])\n",
" s = solutions[key][0]\n",
" break\n",
" except KeyError:\n",
" solutions[key] = [cube]\n",
"\n",
"print(s)\n",
"assert(s == 127035954683)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 6 Jan 2019, 05:47",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"cubes"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,106 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Powerful digit counts (Euler Problem 63)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"The 5-digit number, 16807=$7^5$, is also a fifth power. Similarly, the 9-digit number, 134217728=$8^9$, is a ninth power.\n",
"\n",
"How many n-digit positive integers exist which are also an nth power?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def get_digit_count(n):\n",
" if n < 10:\n",
" return 1\n",
" c = 0\n",
" while n:\n",
" n //= 10\n",
" c += 1\n",
" return c\n",
"\n",
"assert(get_digit_count(0) == 1)\n",
"assert(get_digit_count(1) == 1)\n",
"assert(get_digit_count(33) == 2)\n",
"assert(get_digit_count(100) == 3)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"49\n"
]
}
],
"source": [
"def get_n_digit_positive_integers(n):\n",
" r = []\n",
" i = 1\n",
" while True:\n",
" if get_digit_count(i ** n) == n:\n",
" r.append(i ** n)\n",
" if get_digit_count(i ** n) > n:\n",
" return r\n",
" i += 1\n",
"\n",
"s = sum([len(get_n_digit_positive_integers(n)) for n in range(1, 1000)])\n",
"print(s)\n",
"assert(s == 49)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Sun, 6 Jan 2019, 06:17",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"powers"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,213 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Odd period square roots (Euler Problem 64)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"[https://projecteuler.net/problem=64](https://projecteuler.net/problem=64)\n",
"\n",
"The first ten continued fraction representations of (irrational) square roots are:\n",
"\n",
"√2=[1;(2)], period=1\n",
"\n",
"√3=[1;(1,2)], period=2\n",
"\n",
"√5=[2;(4)], period=1\n",
"\n",
"√6=[2;(2,4)], period=2\n",
"\n",
"√7=[2;(1,1,1,4)], period=4\n",
"\n",
"√8=[2;(1,4)], period=2\n",
"\n",
"√10=[3;(6)], period=1\n",
"\n",
"√11=[3;(3,6)], period=2\n",
"\n",
"√12= [3;(2,6)], period=2\n",
"\n",
"√13=[3;(1,1,1,1,6)], period=5\n",
"\n",
"Exactly four continued fractions, for N ≤ 13, have an odd period.\n",
"\n",
"How many continued fractions for N ≤ 10000 have an odd period?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"\n",
"def get_floor_sqrt(n):\n",
" return math.floor(math.sqrt(n))\n",
"\n",
"assert(get_floor_sqrt(5) == 2)\n",
"assert(get_floor_sqrt(23) == 4)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3, 3, 2)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def next_expansion(current_a, current_nominator, current_denominator, original_number):\n",
" # Less typing\n",
" cn = current_nominator\n",
" cd = current_denominator\n",
"\n",
" # Step 1: Multiply the fraction so that we can use the third binomial formula.\n",
" # Make sure we can reduce the nominator.\n",
" assert((original_number - cd * cd) % cn == 0)\n",
" # The new nominator is the denominator since we multiply with (x + cd) and then\n",
" # reduce the previous nominator.\n",
" # The new denominator is calculated by applying the third binomial formula and\n",
" # then by divided by the previous nominator.\n",
" cn, cd = cd, (original_number - cd * cd) // cn\n",
" \n",
" # Step 2: Calculate the next a by finding the next floor square root.\n",
" next_a = math.floor((math.sqrt(original_number) + cn) // cd)\n",
" \n",
" # Step 3: Remove next a from the fraction by substracting it.\n",
" cn = cn - next_a * cd\n",
" cn *= -1\n",
" \n",
" return next_a, cn, cd\n",
"\n",
"next_expansion(1, 7, 3, 23)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def get_continued_fraction_sequence(n):\n",
" \n",
" # If number is a square number we return it.\n",
" floor_sqrt = get_floor_sqrt(n)\n",
" if n == floor_sqrt * floor_sqrt:\n",
" return ((floor_sqrt), [])\n",
" \n",
" # Otherwise, we calculate the next expansion till we\n",
" # encounter a step a second time. \n",
" a = floor_sqrt\n",
" cn = a\n",
" cd = 1\n",
" sequence = []\n",
" previous_steps = []\n",
" \n",
" while not (a, cn, cd) in previous_steps :\n",
" #print(\"a: {} cn: {} cd: {}\".format(a, cn, cd))\n",
" previous_steps.append((a, cn, cd))\n",
" a, cn, cd = next_expansion(a, cd, cn, n)\n",
" sequence.append(a)\n",
" sequence.pop()\n",
" return ((floor_sqrt), sequence)\n",
"\n",
"assert(get_continued_fraction_sequence(1) == ((1), []))\n",
"assert(get_continued_fraction_sequence(4) == ((2), []))\n",
"assert(get_continued_fraction_sequence(25) == ((5), []))\n",
"assert(get_continued_fraction_sequence(2) == ((1), [2]))\n",
"assert(get_continued_fraction_sequence(3) == ((1), [1,2]))\n",
"assert(get_continued_fraction_sequence(5) == ((2), [4]))\n",
"assert(get_continued_fraction_sequence(13) == ((3), [1,1,1,1,6]))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_period(n):\n",
" _, sequence = get_continued_fraction_sequence(n)\n",
" return len(sequence)\n",
"\n",
"assert(get_period(23) == 4)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1322\n"
]
}
],
"source": [
"s = len([n for n in range(1, 10001) if get_period(n) % 2 != 0])\n",
"print(s)\n",
"assert(s == 1322)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Tue, 22 Jan 2019, 05:10",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"fractions",
"square roots",
"sequence",
"periodic"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,116 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Convergents of e (Euler Problem 65)\n",
"\n",
"Hence the sequence of the first ten convergents for √2 are:\n",
"\n",
"1, 3/2, 7/5, 17/12, 41/29, 99/70, 239/169, 577/408, 1393/985, 3363/2378, ...\n",
"\n",
"What is most surprising is that the important mathematical constant,\n",
"\n",
"e = [2; 1,2,1, 1,4,1, 1,6,1 , ... , 1,2k,1, ...].\n",
"\n",
"The first ten terms in the sequence of convergents for e are:\n",
"\n",
"2, 3, 8/3, 11/4, 19/7, 87/32, 106/39, 193/71, 1264/465, 1457/536, ...\n",
"\n",
"The sum of digits in the numerator of the 10th convergent is 1+4+5+7=17.\n",
"\n",
"Find the sum of digits in the numerator of the 100th convergent of the continued fraction for e."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def gcd(a, b):\n",
" if b > a:\n",
" a, b = b, a\n",
" while a % b != 0:\n",
" a, b = b, a % b\n",
" return b\n",
"\n",
"def add_fractions(n1, d1, n2, d2):\n",
" d = d1 * d2\n",
" n1 = n1 * (d // d1)\n",
" n2 = n2 * (d // d2)\n",
" n = n1 + n2\n",
" p = gcd(n, d)\n",
" return (n // p, d // p)\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"272\n"
]
}
],
"source": [
"def next_expansion(previous_numerator, previous_denumerator, value):\n",
" if previous_numerator == 0:\n",
" return (value, 1)\n",
" return add_fractions(previous_denumerator, previous_numerator, value, 1)\n",
"\n",
"e_sequence = [2] + [n for i in range(2, 1000, 2) for n in (1, i, 1)]\n",
"\n",
"n, d = 0, 1\n",
"\n",
"for i in range(100, 0, -1):\n",
" n, d = next_expansion(n, d, e_sequence[i - 1])\n",
"\n",
"s = sum([int(l) for l in str(n)])\n",
"print(s)\n",
"assert(s == 272)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Wed, 23 Jan 2019, 05:54",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"expansion",
"e",
"sequence"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,279 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Diophantine equation (Euler Problem 66)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"Consider quadratic Diophantine equations of the form:\n",
"\n",
"$x^2 Dy^2 = 1$\n",
"\n",
"For example, when D=13, the minimal solution in x is 6492 13×1802 = 1.\n",
"\n",
"It can be assumed that there are no solutions in positive integers when D is square.\n",
"\n",
"By finding minimal solutions in x for D = {2, 3, 5, 6, 7}, we obtain the following:\n",
"\n",
"$3^2 2×2^2 = 1$\n",
"\n",
"$2^2 3×1^2 = 1$\n",
"\n",
"$9^2 5×4^2 = 1$\n",
"\n",
"$5^2 6×2^2 = 1$\n",
"\n",
"$8^2 7×3^2 = 1$\n",
"\n",
"Hence, by considering minimal solutions in x for D ≤ 7, the largest x is obtained when D=5.\n",
"\n",
"Find the value of D ≤ 1000 in minimal solutions of x for which the largest value of x is obtained.\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import math\n",
"\n",
"def get_floor_sqrt(n):\n",
" return math.floor(math.sqrt(n))\n",
"\n",
"assert(get_floor_sqrt(5) == 2)\n",
"assert(get_floor_sqrt(23) == 4)\n",
"\n",
"def next_expansion_1(current_a, current_nominator, current_denominator, original_number):\n",
" cn = current_nominator\n",
" cd = current_denominator\n",
" cn, cd = cd, (original_number - cd * cd) // cn\n",
" next_a = math.floor((math.sqrt(original_number) + cn) // cd)\n",
" cn = cn - next_a * cd\n",
" cn *= -1\n",
" \n",
" return next_a, cn, cd\n",
"\n",
"def get_continued_fraction_sequence(n):\n",
" \n",
" # If number is a square number we return it.\n",
" floor_sqrt = get_floor_sqrt(n)\n",
" if n == floor_sqrt * floor_sqrt:\n",
" return ((floor_sqrt), [])\n",
" \n",
" # Otherwise, we calculate the next expansion till we\n",
" # encounter a step a second time. \n",
" a = floor_sqrt\n",
" cn = a\n",
" cd = 1\n",
" sequence = []\n",
" previous_steps = []\n",
" \n",
" while not (a, cn, cd) in previous_steps :\n",
" #print(\"a: {} cn: {} cd: {}\".format(a, cn, cd))\n",
" previous_steps.append((a, cn, cd))\n",
" a, cn, cd = next_expansion_1(a, cd, cn, n)\n",
" sequence.append(a)\n",
" sequence.pop()\n",
" return ((floor_sqrt), sequence)\n",
"\n",
"def get_continued_fraction_sequence(n):\n",
" \n",
" # If number is a square number we return it.\n",
" floor_sqrt = get_floor_sqrt(n)\n",
" if n == floor_sqrt * floor_sqrt:\n",
" return ((floor_sqrt), [])\n",
" \n",
" # Otherwise, we calculate the next expansion till we\n",
" # encounter a step a second time. \n",
" a = floor_sqrt\n",
" cn = a\n",
" cd = 1\n",
" sequence = []\n",
" previous_steps = []\n",
" \n",
" while not (a, cn, cd) in previous_steps :\n",
" #print(\"a: {} cn: {} cd: {}\".format(a, cn, cd))\n",
" previous_steps.append((a, cn, cd))\n",
" a, cn, cd = next_expansion_1(a, cd, cn, n)\n",
" sequence.append(a)\n",
" sequence.pop()\n",
" return ((floor_sqrt), sequence)\n",
"\n",
"assert(get_continued_fraction_sequence(1) == ((1), []))\n",
"assert(get_continued_fraction_sequence(4) == ((2), []))\n",
"assert(get_continued_fraction_sequence(25) == ((5), []))\n",
"assert(get_continued_fraction_sequence(2) == ((1), [2]))\n",
"assert(get_continued_fraction_sequence(3) == ((1), [1,2]))\n",
"assert(get_continued_fraction_sequence(5) == ((2), [4]))\n",
"assert(get_continued_fraction_sequence(13) == ((3), [1,1,1,1,6]))"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def gcd(a, b):\n",
" if b > a:\n",
" a, b = b, a\n",
" while a % b != 0:\n",
" a, b = b, a % b\n",
" return b\n",
"\n",
"def add_fractions(n1, d1, n2, d2):\n",
" d = d1 * d2\n",
" n1 = n1 * (d // d1)\n",
" n2 = n2 * (d // d2)\n",
" n = n1 + n2\n",
" p = gcd(n, d)\n",
" return (n // p, d // p)\n",
"\n",
"def next_expansion_2(previous_numerator, previous_denumerator, value):\n",
" if previous_numerator == 0:\n",
" return (value, 1)\n",
" return add_fractions(previous_denumerator, previous_numerator, value, 1)\n",
" \n",
"def get_fractions(n, x):\n",
" #print(\"get_fractions(n={}, x={})\".format(n, x))\n",
" # Get sequence of a_x\n",
" first_value, sequence = get_continued_fraction_sequence(n)\n",
" sequence = [first_value] + math.ceil(x / len(sequence)) * sequence\n",
" sequence = sequence[:x + 1]\n",
" sequence = sequence[::-1]\n",
" \n",
" n, d = 0, 1\n",
" for s in sequence:\n",
" n, d = next_expansion_2(n, d, s)\n",
" return (n, d)\n",
"\n",
"assert(get_fractions(7, 0) == (2, 1))\n",
"assert(get_fractions(7, 1) == (3, 1))\n",
"assert(get_fractions(7, 2) == (5, 2))\n",
"assert(get_fractions(7, 3) == (8, 3))"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def get_minimal_solution(d):\n",
" for i in range(0, 100):\n",
" x, y = get_fractions(d, i)\n",
" if x * x - d * y * y == 1:\n",
" return((x, y))\n",
"\n",
"assert(get_minimal_solution(2) == (3, 2))\n",
"assert(get_minimal_solution(3) == (2, 1))\n",
"assert(get_minimal_solution(85) == (285769, 30996))\n",
"assert(get_minimal_solution(109) == (158070671986249, 15140424455100))"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"True\n"
]
}
],
"source": [
"from math import sqrt\n",
"\n",
"def is_square(n):\n",
" return sqrt(n).is_integer()\n",
"\n",
"print(is_square(4))"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"d: 661 x: 16421658242965910275055840472270471049\n"
]
}
],
"source": [
"x_max = 0\n",
"d_max = 0\n",
"\n",
"for d in range(2, 1001):\n",
" if is_square(d):\n",
" continue\n",
" \n",
" x, y = get_minimal_solution(d)\n",
" if x > x_max:\n",
" x_max = x\n",
" d_max = d\n",
"\n",
"print(\"d: {} x: {}\".format(d_max, x_max))\n",
"s = d_max\n",
"assert(s == 661)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "Mon, 28 Jan 2019, 21:08",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": [
"diophantine",
"equation",
"pell's equation"
]
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@ -1,95 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Euler Problem 67\n",
"\n",
"By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.\n",
"\n",
"~~~\n",
" 3\n",
" 7 4\n",
" 2 4 6\n",
"8 5 9 3\n",
"~~~\n",
"\n",
"That is, 3 + 7 + 4 + 9 = 23.\n",
"\n",
"Find the maximum total from top to bottom in triangle.txt (right click and 'Save Link/Target As...'), a 15K text file containing a triangle with one-hundred rows.\n",
"\n",
"NOTE: This is a much more difficult version of Problem 18. It is not possible to try every route to solve this problem, as there are 299 altogether! If you could check one trillion (1012) routes every second it would take over twenty billion years to check them all. There is an efficient algorithm to solve it. ;o)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So let's hope our solution is good. I have saved the triangle in a file EulerProblem067.txt in the same directory as this notebook."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"7273\n"
]
}
],
"source": [
"def find_greatest_path_sum_in_triangle_string(ts):\n",
" from functools import reduce\n",
" xss = [list(map(int, xs.split())) for xs in ts.split(\"\\n\") if xs]\n",
" xss.reverse()\n",
" r = lambda xs, ys: [max([xs[i] + ys[i], xs[i + 1] + ys[i]]) for i in range(len(ys))]\n",
" return reduce(r, xss[1:], xss[0])[0]\n",
"\n",
"with open('EulerProblem067.txt', 'r') as f:\n",
" triangle_string = f.read()\n",
" \n",
"print(find_greatest_path_sum_in_triangle_string(triangle_string))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Well, that was fast."
]
}
],
"metadata": {
"completion_date": "Fri, 5 Sep 2014, 07:36",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.4"
},
"tags": [
"reduce",
"triangle"
]
},
"nbformat": 4,
"nbformat_minor": 0
}

View File

@ -1,44 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Magic 5-gon ring (Euler Problem 68)\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"completion_date": "",
"kernelspec": {
"display_name": "Python 3",
"language": "python3.6",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
},
"tags": []
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More