|
| 1 | +# <https://projecteuler.net/problem=751> |
| 2 | +# <p>A non-decreasing sequence of integers $a_n$ can be generated from any positive real value $\theta$ by the following procedure: |
| 3 | +# $$\begin{align} |
| 4 | +# \begin{split} |
| 5 | +# b_1 &= \theta \\ |
| 6 | +# b_n &= \left\lfloor b_{n-1} \right\rfloor \left(b_{n-1} - \left\lfloor b_{n-1} \right\rfloor + 1\right)~~~\forall ~ n \geq 2 \\ |
| 7 | +# a_n &= \left\lfloor b_{n} \right\rfloor |
| 8 | +# \end{split} |
| 9 | +# \end{align}$$ |
| 10 | +# Where $\left\lfloor \cdot \right\rfloor$ is the floor function.</p> |
| 11 | +# |
| 12 | +# <p>For example, $\theta=2.956938891377988...$ generates the Fibonacci sequence: $2, 3, 5, 8, 13, 21, 34, 55, 89, ...$</p> |
| 13 | +# |
| 14 | +# <p>The <i>concatenation</i> of a sequence of positive integers $a_n$ is a real value denoted $\tau$ constructed by concatenating the elements of the sequence after the decimal point, starting at $a_1$: $a_1.a_2a_3a_4...$</p> |
| 15 | +# |
| 16 | +# <p>For example, the Fibonacci sequence constructed from $\theta=2.956938891377988...$ yields the concatenation $\tau=2.3581321345589...$ Clearly, $\tau \neq \theta$ for this value of $\theta$.</p> |
| 17 | +# |
| 18 | +# <p>Find the only value of $\theta$ for which the generated sequence starts at $a_1=2$ and the concatenation of the generated sequence equals the original value: $\tau = \theta$. Give your answer rounded to $24$ places after the decimal point.</p> |
| 19 | +# Notes: |
| 20 | +# - Since it starts with 2, a1 is 2 and theta must round down to 2 |
| 21 | +# - a2 is either 2 or 3, depending on whether or not the decimal places round up or down (since they get doubled) |
| 22 | +# - Since the tenths place in theta is a 2 or 3, it must round down. So a2 is 2. |
| 23 | +# - a3 is either 2 or 3, depending on whether or not the decimal places round up or down (since they get doubled) |
| 24 | +# - Theta is currently 2.2, so b1 = 2.2, b2 = 2.4 (or 2.5). In either case, a3 must be 2 |
| 25 | +# - b3 must be greater than (or equal to) 2.5. So a4 must be 3 |
| 26 | +# - Theta is now 2.223 |
| 27 | + |
| 28 | +from math import floor |
| 29 | +from decimal import * |
| 30 | + |
| 31 | +def b(theta, n): |
| 32 | + if n == 1: return theta |
| 33 | + solution = theta |
| 34 | + while n > 1: |
| 35 | + solution = floor(solution) * (solution - floor(solution) + 1) |
| 36 | + n -= 1 |
| 37 | + return solution |
| 38 | + |
| 39 | +def test_b_works(): |
| 40 | + assert 2 == b(2, 1) |
| 41 | + assert Decimal('2.4') == b(Decimal('2.2'), 2) |
| 42 | + |
| 43 | +def a_sequence(theta): |
| 44 | + solution = str(floor(b(theta,1))) + "." |
| 45 | + for i in range(2,25): |
| 46 | + solution += str(floor(b(theta,i))) |
| 47 | + return solution |
| 48 | + |
| 49 | +def theta_generator(theta=2): |
| 50 | + stringy_theta = str(theta) |
| 51 | + if len(stringy_theta) >= 26: |
| 52 | + return theta |
| 53 | + solution = a_sequence(theta) |
| 54 | + stringy_solution = str(solution) |
| 55 | + if stringy_solution.startswith(stringy_theta): |
| 56 | + next = stringy_solution[len(stringy_theta)] |
| 57 | + if next == ".": |
| 58 | + next += stringy_solution[len(stringy_theta) + 1] |
| 59 | + return theta_generator(Decimal(stringy_theta + next)) |
| 60 | + else: |
| 61 | + return -1 |
| 62 | + |
| 63 | +def test_works(): |
| 64 | + assert Decimal('2.223561019313554106173177') == theta_generator() |
0 commit comments