From fc7c74c3239c805b39fac655f7d7b6b563171ebc Mon Sep 17 00:00:00 2001 From: filifa Date: Thu, 15 May 2025 23:30:57 -0400 Subject: [PATCH] refer to relevant problems instead of re-implementing --- notebooks/problem0065.ipynb | 41 ++++++++++++++++------------- notebooks/problem0066.ipynb | 51 ++++++++----------------------------- 2 files changed, 34 insertions(+), 58 deletions(-) diff --git a/notebooks/problem0065.ipynb b/notebooks/problem0065.ipynb index 5782a09..bec1216 100644 --- a/notebooks/problem0065.ipynb +++ b/notebooks/problem0065.ipynb @@ -36,7 +36,7 @@ "id": "396468b7", "metadata": {}, "source": [ - "If we wanted to compute the convergents ourselves, we could first make a generator for the partial denominators of the continued fraction of $e$." + "To compute the convergents ourselves, we'll first make a generator for the partial denominators of the continued fraction of $e$." ] }, { @@ -48,14 +48,9 @@ "source": [ "from itertools import count, chain\n", "\n", - "def partial_denominators_e(n):\n", + "def partial_denominators_e():\n", " yield 2\n", - " denominators = chain.from_iterable((1, 2 * k, 1) for k in count(1))\n", - " for (i, b) in enumerate(denominators):\n", - " if i >= n:\n", - " break\n", - " \n", - " yield b" + " yield from chain.from_iterable((1, 2 * k, 1) for k in count(1))" ] }, { @@ -63,7 +58,7 @@ "id": "33288cd0", "metadata": {}, "source": [ - "Then write a function for computing a continued fraction from a sequence of partial denominators (outside of SageMath, you might want to use a [fraction type](https://docs.python.org/3/library/fractions.html))." + "Then we'll apply a simple algorithm for computing [convergents using the partial denominators](https://en.wikipedia.org/wiki/Simple_continued_fraction) (outside of SageMath, you might want to use a [fraction type](https://docs.python.org/3/library/fractions.html))." ] }, { @@ -73,13 +68,21 @@ "metadata": {}, "outputs": [], "source": [ - "def cf(denominators):\n", - " a = next(denominators)\n", - " \n", - " try:\n", - " return a + 1 / cf(denominators)\n", - " except StopIteration:\n", - " return a" + "def convergents(partial_denoms):\n", + " h, hprev = 1, 0\n", + " k, kprev = 0, 1\n", + " for b in partial_denoms:\n", + " h, hprev = b * h + hprev, h\n", + " k, kprev = b * k + kprev, k\n", + " yield h/k" + ] + }, + { + "cell_type": "markdown", + "id": "99b790f3", + "metadata": {}, + "source": [ + "Now just iterate until we reach the 100th convergent." ] }, { @@ -100,7 +103,11 @@ } ], "source": [ - "sum(cf(partial_denominators_e(99)).numerator().digits())" + "for (i, c) in enumerate(convergents(partial_denominators_e())):\n", + " if i == 99:\n", + " break\n", + "\n", + "sum(c.numerator().digits())" ] }, { diff --git a/notebooks/problem0066.ipynb b/notebooks/problem0066.ipynb index ab729eb..7a6e5fe 100644 --- a/notebooks/problem0066.ipynb +++ b/notebooks/problem0066.ipynb @@ -19,10 +19,10 @@ { "data": { "text/plain": [ - "[(-sqrt(2)*(2*sqrt(2) + 3)^t + sqrt(2)*(-2*sqrt(2) + 3)^t - 3/2*(2*sqrt(2) + 3)^t - 3/2*(-2*sqrt(2) + 3)^t,\n", - " 3/4*sqrt(2)*(2*sqrt(2) + 3)^t - 3/4*sqrt(2)*(-2*sqrt(2) + 3)^t + (2*sqrt(2) + 3)^t + (-2*sqrt(2) + 3)^t),\n", - " (sqrt(2)*(2*sqrt(2) + 3)^t - sqrt(2)*(-2*sqrt(2) + 3)^t + 3/2*(2*sqrt(2) + 3)^t + 3/2*(-2*sqrt(2) + 3)^t,\n", - " -3/4*sqrt(2)*(2*sqrt(2) + 3)^t + 3/4*sqrt(2)*(-2*sqrt(2) + 3)^t - (2*sqrt(2) + 3)^t - (-2*sqrt(2) + 3)^t)]" + "[(sqrt(2)*(2*sqrt(2) + 3)^t - sqrt(2)*(-2*sqrt(2) + 3)^t + 3/2*(2*sqrt(2) + 3)^t + 3/2*(-2*sqrt(2) + 3)^t,\n", + " -3/4*sqrt(2)*(2*sqrt(2) + 3)^t + 3/4*sqrt(2)*(-2*sqrt(2) + 3)^t - (2*sqrt(2) + 3)^t - (-2*sqrt(2) + 3)^t),\n", + " (-sqrt(2)*(2*sqrt(2) + 3)^t + sqrt(2)*(-2*sqrt(2) + 3)^t - 3/2*(2*sqrt(2) + 3)^t - 3/2*(-2*sqrt(2) + 3)^t,\n", + " 3/4*sqrt(2)*(2*sqrt(2) + 3)^t - 3/4*sqrt(2)*(-2*sqrt(2) + 3)^t + (2*sqrt(2) + 3)^t + (-2*sqrt(2) + 3)^t)]" ] }, "execution_count": 1, @@ -97,51 +97,20 @@ "## Solving Pell equations\n", "Lagrange proved that if $(x_0, y_0)$ is a solution to\n", "$$x^2 - dy^2 = 1$$\n", - "then $\\frac{x_0}{y_0}$ is a [convergent of the continued fraction](https://en.wikipedia.org/wiki/Simple_continued_fraction) of $\\sqrt{d}$. This is great for us, since we can write generators for computing convergents of square roots (FYI, SageMath can do this with built-in methods: `continued_fraction(sqrt(d)).convergents()`)." + "then $\\frac{x_0}{y_0}$ is a [convergent of the continued fraction](https://en.wikipedia.org/wiki/Simple_continued_fraction) of $\\sqrt{d}$. This is great for us, since there are algorithms to compute these convergents. We'll use SageMath here; see [problem 64](https://projecteuler.net/problem=64) for how to compute the partial denominators of the continued fraction of a square root, and see [problem 65](https://projecteuler.net/problem=65) for an algorithm that uses partial denominators to compute convergents of continued fractions.\n", + "\n", + "Here, we iterate over each convergent to see if its numerator and denominator are a solution to the Pell equation." ] }, { "cell_type": "code", "execution_count": 4, - "id": "c51f9b7e", - "metadata": {}, - "outputs": [], - "source": [ - "def continued_fraction_sqrt(d):\n", - " x = sqrt(d)\n", - " while True:\n", - " b = floor(x)\n", - " yield b\n", - " x = (x - b)^-1\n", - " \n", - " \n", - "def convergents(partial_denoms):\n", - " h, hprev = 1, 0\n", - " k, kprev = 0, 1\n", - " for b in partial_denoms:\n", - " h, hprev = b * h + hprev, h\n", - " k, kprev = b * k + kprev, k\n", - " yield h/k" - ] - }, - { - "cell_type": "markdown", - "id": "d5cbf5eb", - "metadata": {}, - "source": [ - "Then we can just iterate over each convergent to see if its numerator and denominator are a solution to the Pell equation." - ] - }, - { - "cell_type": "code", - "execution_count": 5, "id": "5d95125c", "metadata": {}, "outputs": [], "source": [ "def pell_fundamental_solution(d):\n", - " partial_denoms = continued_fraction_sqrt(d)\n", - " for f in convergents(partial_denoms):\n", + " for f in continued_fraction(sqrt(d)).convergents():\n", " x, y = f.as_integer_ratio()\n", " if x^2 - d*y^2 == 1:\n", " return (x, y)" @@ -157,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "03d7ba9d", "metadata": {}, "outputs": [ @@ -167,7 +136,7 @@ "661" ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" }