diff --git a/ipython/EulerProblem063.ipynb b/ipython/EulerProblem063.ipynb index 2e15469..4a6cb71 100644 --- a/ipython/EulerProblem063.ipynb +++ b/ipython/EulerProblem063.ipynb @@ -13,11 +13,61 @@ "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", + "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, @@ -29,7 +79,7 @@ } ], "metadata": { - "completion_date": "", + "completion_date": "Sun, 6 Jan 2019, 06:17", "kernelspec": { "display_name": "Python 3", "language": "python3.6", @@ -47,7 +97,9 @@ "pygments_lexer": "ipython3", "version": "3.6.5" }, - "tags": [] + "tags": [ + "powers" + ] }, "nbformat": 4, "nbformat_minor": 2 diff --git a/ipython/EulerProblem064.ipynb b/ipython/EulerProblem064.ipynb new file mode 100644 index 0000000..3f53012 --- /dev/null +++ b/ipython/EulerProblem064.ipynb @@ -0,0 +1,213 @@ +{ + "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 +} diff --git a/ipython/html/EulerProblem063.html b/ipython/html/EulerProblem063.html index ce8c2fe..64c5fd6 100644 --- a/ipython/html/EulerProblem063.html +++ b/ipython/html/EulerProblem063.html @@ -11778,13 +11778,70 @@ div#notebook {
The 5-digit number, 16807=75, is also a fifth power. Similarly, the 9-digit number, 134217728=89, is a ninth power.
+The 5-digit number, 16807=$7^5$, is also a fifth power. Similarly, the 9-digit number, 134217728=$8^9$, is a ninth power.
How many n-digit positive integers exist which are also an nth power?
def get_digit_count(n):
+ if n < 10:
+ return 1
+ c = 0
+ while n:
+ n //= 10
+ c += 1
+ return c
+
+assert(get_digit_count(0) == 1)
+assert(get_digit_count(1) == 1)
+assert(get_digit_count(33) == 2)
+assert(get_digit_count(100) == 3)
+def get_n_digit_positive_integers(n):
+ r = []
+ i = 1
+ while True:
+ if get_digit_count(i ** n) == n:
+ r.append(i ** n)
+ if get_digit_count(i ** n) > n:
+ return r
+ i += 1
+
+s = sum([len(get_n_digit_positive_integers(n)) for n in range(1, 1000)])
+print(s)
+assert(s == 49)
+https://projecteuler.net/problem=64
+The first ten continued fraction representations of (irrational) square roots are:
+√2=[1;(2)], period=1
+√3=[1;(1,2)], period=2
+√5=[2;(4)], period=1
+√6=[2;(2,4)], period=2
+√7=[2;(1,1,1,4)], period=4
+√8=[2;(1,4)], period=2
+√10=[3;(6)], period=1
+√11=[3;(3,6)], period=2
+√12= [3;(2,6)], period=2
+√13=[3;(1,1,1,1,6)], period=5
+Exactly four continued fractions, for N ≤ 13, have an odd period.
+How many continued fractions for N ≤ 10000 have an odd period?
+import math
+
+def get_floor_sqrt(n):
+ return math.floor(math.sqrt(n))
+
+assert(get_floor_sqrt(5) == 2)
+assert(get_floor_sqrt(23) == 4)
+def next_expansion(current_a, current_nominator, current_denominator, original_number):
+ # Less typing
+ cn = current_nominator
+ cd = current_denominator
+
+ # Step 1: Multiply the fraction so that we can use the third binomial formula.
+ # Make sure we can reduce the nominator.
+ assert((original_number - cd * cd) % cn == 0)
+ # The new nominator is the denominator since we multiply with (x + cd) and then
+ # reduce the previous nominator.
+ # The new denominator is calculated by applying the third binomial formula and
+ # then by divided by the previous nominator.
+ cn, cd = cd, (original_number - cd * cd) // cn
+
+ # Step 2: Calculate the next a by finding the next floor square root.
+ next_a = math.floor((math.sqrt(original_number) + cn) // cd)
+
+ # Step 3: Remove next a from the fraction by substracting it.
+ cn = cn - next_a * cd
+ cn *= -1
+
+ return next_a, cn, cd
+
+next_expansion(1, 7, 3, 23)
+def get_continued_fraction_sequence(n):
+
+ # If number is a square number we return it.
+ floor_sqrt = get_floor_sqrt(n)
+ if n == floor_sqrt * floor_sqrt:
+ return ((floor_sqrt), [])
+
+ # Otherwise, we calculate the next expansion till we
+ # encounter a step a second time.
+ a = floor_sqrt
+ cn = a
+ cd = 1
+ sequence = []
+ previous_steps = []
+
+ while not (a, cn, cd) in previous_steps :
+ #print("a: {} cn: {} cd: {}".format(a, cn, cd))
+ previous_steps.append((a, cn, cd))
+ a, cn, cd = next_expansion(a, cd, cn, n)
+ sequence.append(a)
+ sequence.pop()
+ return ((floor_sqrt), sequence)
+
+assert(get_continued_fraction_sequence(1) == ((1), []))
+assert(get_continued_fraction_sequence(4) == ((2), []))
+assert(get_continued_fraction_sequence(25) == ((5), []))
+assert(get_continued_fraction_sequence(2) == ((1), [2]))
+assert(get_continued_fraction_sequence(3) == ((1), [1,2]))
+assert(get_continued_fraction_sequence(5) == ((2), [4]))
+assert(get_continued_fraction_sequence(13) == ((3), [1,1,1,1,6]))
+def get_period(n):
+ _, sequence = get_continued_fraction_sequence(n)
+ return len(sequence)
+
+assert(get_period(23) == 4)
+s = len([n for n in range(1, 10001) if get_period(n) % 2 != 0])
+print(s)
+assert(s == 1322)
+
+