diff --git a/ipython/EulerProblem058.ipynb b/ipython/EulerProblem058.ipynb index f7622b9..c68c6d0 100644 --- a/ipython/EulerProblem058.ipynb +++ b/ipython/EulerProblem058.ipynb @@ -17,19 +17,250 @@ "\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", + " 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": {}, + "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(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(3))\n", + "assert(fermat_test(107))\n", + "assert(fermat_test(108) == False)\n", + "assert(fermat_test(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": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import random\n", + "\n", + "def is_prime(n):\n", + " if n == 1:\n", + " return False\n", + " for _ in range(100):\n", + " a = n - random.randint(1, n - 1)\n", + " if not expmod(a, n, n) == a:\n", + " return False\n", + " return True\n", + "\n", + "assert(fermat_test(3))\n", + "assert(fermat_test(107))\n", + "assert(fermat_test(108) == False)\n", + "assert(fermat_test(109))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "n: 26641 count_total: 53281 count_primes: 5328 ratio: 0.09999812315834913\n" + ] + } + ], + "source": [ + "s = get_solution()" + ] + }, + { + "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/Miller–Rabin_primality_test](https://en.wikipedia.org/wiki/Miller–Rabin_primality_test)." + ] + }, { "cell_type": "code", "execution_count": null, @@ -41,7 +272,7 @@ } ], "metadata": { - "completion_date": "", + "completion_date": "Sat, 29 Dec 2018, 09:00", "kernelspec": { "display_name": "Python 3", "language": "python3.6", @@ -59,7 +290,13 @@ "pygments_lexer": "ipython3", "version": "3.6.5" }, - "tags": [] + "tags": [ + "prime", + "fermat", + "spiral", + "diagonal", + "todo" + ] }, "nbformat": 4, "nbformat_minor": 2 diff --git a/ipython/EulerProblem061.ipynb b/ipython/EulerProblem061.ipynb new file mode 100644 index 0000000..1b83761 --- /dev/null +++ b/ipython/EulerProblem061.ipynb @@ -0,0 +1,73 @@ +{ + "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(3n−1)/2\t \t1, 5, 12, 22, 35, ...\n", + "\n", + "Hexagonal\t \tP6,n=n(2n−1)\t \t1, 6, 15, 28, 45, ...\n", + "\n", + "Heptagonal\t \tP7,n=n(5n−3)/2\t \t1, 7, 18, 34, 55, ...\n", + "\n", + "Octagonal\t \tP8,n=n(3n−2)\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": 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 +} diff --git a/ipython/EulerProblem062.ipynb b/ipython/EulerProblem062.ipynb new file mode 100644 index 0000000..16f56cd --- /dev/null +++ b/ipython/EulerProblem062.ipynb @@ -0,0 +1,56 @@ +{ + "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": 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 +} diff --git a/ipython/EulerProblem063.ipynb b/ipython/EulerProblem063.ipynb new file mode 100644 index 0000000..2e15469 --- /dev/null +++ b/ipython/EulerProblem063.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Powerful digit counts (Euler Problem 63)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "The 5-digit number, 16807=75, is also a fifth power. Similarly, the 9-digit number, 134217728=89, is a ninth power.\n", + "\n", + "How many n-digit positive integers exist which are also an nth power?" + ] + }, + { + "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 +} diff --git a/ipython/html/EulerProblem058.html b/ipython/html/EulerProblem058.html index c25e6e6..063afb0 100644 --- a/ipython/html/EulerProblem058.html +++ b/ipython/html/EulerProblem058.html @@ -11780,13 +11780,15 @@ div#notebook {
https://projecteuler.net/problem=58
Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.
-37 36 35 34 33 32 31 +
37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 5 4 3 12 29
40 19 6 1 2 11 28
41 20 7 8 9 10 27
42 21 22 23 24 25 26
-43 44 45 46 47 48 49
+43 44 45 46 47 48 49
+
+
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%.
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%?
def get_last_corner_value(side_length):
+ return side_length * side_length
+
+assert(get_last_corner_value(1) == 1)
+assert(get_last_corner_value(3) == 9)
+assert(get_last_corner_value(5) == 25)
+
+
+def get_corner_values(side_length):
+ if side_length == 1:
+ return [1]
+ return [get_last_corner_value(side_length) - i * (side_length - 1)
+ for i in range(0, 4)][::-1]
+
+assert(get_corner_values(1) == [1])
+assert(get_corner_values(3) == [3, 5, 7, 9])
+assert(get_corner_values(5) == [13, 17, 21, 25])
+assert(get_corner_values(7) == [31, 37, 43, 49])
+
+
+def get_diagonal_values(side_length):
+ return [corner_value
+ for length in range(1, side_length + 1, 2)
+ for corner_value in get_corner_values(length)
+ ]
+
+assert(get_diagonal_values(1) == [1])
+assert(get_diagonal_values(3) == [1, 3, 5, 7, 9])
+assert(get_diagonal_values(5) == [1, 3, 5, 7, 9, 13, 17, 21, 25])
+def expmod(base, exp, m):
+ if exp == 0:
+ return 1
+ if (exp % 2 == 0):
+ return (expmod(base, exp // 2, m) ** 2 % m)
+ return (base * expmod(base, exp - 1, m) % m)
+
+
+def fermat_test(n):
+ if n < 40:
+ return n in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39]
+ a = n - 3
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 5
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 7
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 11
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 13
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 17
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 19
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 23
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 29
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 31
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 37
+ if not expmod(a, n, n) == a:
+ return False
+ a = n - 39
+ if not expmod(a, n, n) == a:
+ return False
+ return True
+
+def trial_division(n):
+ a = []
+ if n % 2 == 0:
+ a.append(2)
+ while n % 2 == 0:
+ n //= 2
+ f = 3
+ while f * f <= n:
+ if n % f == 0:
+ a.append(f)
+ while n % f == 0:
+ n //= f
+ else:
+ f += 2
+ if n != 1:
+ a.append(n)
+ return a
+
+def is_prime(n):
+ if n == 1:
+ return False
+ return trial_division(n)[0] == n
+
+assert(fermat_test(3))
+assert(fermat_test(107))
+assert(fermat_test(108) == False)
+assert(fermat_test(109))
+def get_solution():
+ n = 1
+ count_primes = 0
+ count_total = 0
+ while True:
+ for v in get_corner_values(n):
+ count_total += 1
+ if is_prime(v):
+ count_primes += 1
+ ratio = count_primes / count_total
+ if ratio != 0 and ratio < 0.10:
+ print("n: {} count_total: {} count_primes: {} ratio: {}".format(n, count_total, count_primes, ratio))
+ return n
+ n += 2
+
+s = get_solution()
+print(s)
+assert(s == 26241)
+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.
+import random
+
+def is_prime(n):
+ if n == 1:
+ return False
+ for _ in range(100):
+ a = n - random.randint(1, n - 1)
+ if not expmod(a, n, n) == a:
+ return False
+ return True
+
+assert(fermat_test(3))
+assert(fermat_test(107))
+assert(fermat_test(108) == False)
+assert(fermat_test(109))
+s = get_solution()
+Something seems to be off with my Fermat test...
+Seems like there are systematic errors with the Fermat tests. Certain primes cannot be deteced.
+Try this algorithm instead https://en.wikipedia.org/wiki/Miller–Rabin_primality_test.
+https://projecteuler.net/problem=61
+Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers are all figurate (polygonal) numbers and are generated by the following formulae:
+Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ...
+Square P4,n=n2 1, 4, 9, 16, 25, ...
+Pentagonal P5,n=n(3n−1)/2 1, 5, 12, 22, 35, ...
+Hexagonal P6,n=n(2n−1) 1, 6, 15, 28, 45, ...
+Heptagonal P7,n=n(5n−3)/2 1, 7, 18, 34, 55, ...
+Octagonal P8,n=n(3n−2) 1, 8, 21, 40, 65, ...
+The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three interesting properties.
+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). +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. +This is the only set of 4-digit numbers with this property. +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.
+
+https://projecteuler.net/problem=62
+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.
+Find the smallest cube for which exactly five permutations of its digits are cube.
+
+The 5-digit number, 16807=75, is also a fifth power. Similarly, the 9-digit number, 134217728=89, is a ninth power.
+How many n-digit positive integers exist which are also an nth power?
+
+